Output last inserted primary key value from stored procedure - sql

I'm having a bit of difficulty with this one in that I'm not sure how to do this in SQL Server.
Basically, I want to insert a new row into the database, get the PK value that was just inserted (same query) and output it back to whatever called the stored procedure:
CREATE PROCEDURE Users_Insert
-- Add the parameters for the stored procedure here
#userid int output,
#name varchar(50),
#surname varchar(50),
#email varchar(200),
#password varchar(50),
#location varchar(50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
insert into Users(FirstName, LastName, Email, Password, Location)
values(#name, #surname, #email, #password, #location);
GO
#userid = ##IDENTITY;
END
I've done this in MySQL as follows:
CREATE PROCEDURE Users_Insert(#userid int output, #name varchar(50), #surname varchar(50), #email varchar(200), #password varchar(50), #location varchar(50)
BEGIN
insert into Users(FirstName, LastName, Email, Password, Location)
values(#name, #surname, #email, #password, #location);
set #userid = last_insert_id();
END
SQL Server gives me an error:
Msg 102, Level 15, State 1, Procedure Users_Insert, Line 18
Incorrect syntax near '#userid'.
Frankly, I'm not sure I declared the output parameter correctly, can anyone offer suggestions?

You need to assign the value to #userid ! Also, I would recommend using SCOPE_IDENTITY() and not ##IDENTITY :
CREATE PROCEDURE Users_Insert
-- Add the parameters for the stored procedure here
#userid int output,
#name varchar(50),
#surname varchar(50),
#email varchar(200),
#password varchar(50),
#location varchar(50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
insert into Users(FirstName, LastName, Email, Password, Location)
values(#name, #surname, #email, #password, #location);
-- make an actual **assignment** here...
SELECT #userid = SCOPE_IDENTITY();
END
See this blog post for an explanation as to WHY you should use SCOPE_IDENTITY over ##IDENTITY

Related

create procedure

please hep, I am trying to create a procedure that will display 4 parameters whenever I enter a parameter. This is my code below
CREATE PROCEDURE sp_emp_info
( #EmployeeID INT,
#EmployeeID INT OUTPUT,
#LastName VARCHAR(30) OUTPUT,
#FirstName VARCHAR(15) OUTPUT,
#Phone VARCHAR(10) OUTPUT )
AS
SELECT #EmployeeID,
#LastName,
#FirstName,
#Phone
FROM Employees
WHERE EmployeeID = #EmployeeID
GO
This is bringing this error
The variable name '#EmployeeID' has already been declared. Variable names must be unique within a query batch or stored procedure.
Must declare the scalar variable "#LastName"
I have EmployeeID as both input and output. When I tried to remove the output by running the below :
CREATE PROCEDURE sp_emp_info
( #EmployeeID int,
#LastName VARCHAR(30) OUTPUT,
#FirstName VARCHAR(15) OUTPUT,
#Phone VARCHAR(10) OUTPUT )
AS
SELECT #EmployeeID,
#LastName,
#FirstName,
#Phone
FROM Employees
WHERE EmployeeID = #EmployeeID
GO
that worked, but the procedure wont run . eg I ran
EXECUTE sp_emp_info 7
It brough this error:
Procedure or function 'sp_emp_info' expects parameter '#LastName', which was not supplied.
What do you think I am doing wrong? Thank you .
Okay, I was going about this the complex way. this simple coding:
CREATE PROCEDURE sp_emp_info
( #EmployeeID int )
AS
SELECT EmployeeID,
LastName,
FirstName,
Phone
FROM Employees
WHERE EmployeeID = #EmployeeID
GO
solved my problem.
Thank you everyone.Much appreciated
You need to set a default value for the optional parameters. In this case I set them to NULL.
CREATE PROCEDURE sp_emp_info
( #EmployeeID int )
AS
SELECT EmployeeID
LastName,
FirstName,
Phone
FROM Employees
WHERE EmployeeID = #EmployeeID
GO

Procedure or function has too many arguments SQL server

I getting this error while executing the stored procedure in SQL Server:
Msg 8144, Level 16, State 2, Procedure sp_adduser, Line 2
Procedure or function sp_adduser has too many arguments specified.
The weird thing is that the number of parameters is the same as declared in the procedure, even when I execute it while right-click on the procedure and press execute, input the parameters from the fields and still the same error.
This is the code of the procedure and the exec:
create procedure [dbo].[sp_addUser]
(
#userID nvarchar(50),
#pw nvarchar(50),
#fName nvarchar(50),
#lname nvarchar(50),
#email nvarchar(150),
#address nvarchar(150),
#city int,
#country int,
#phone nvarchar(50),
#gender nvarchar(10),
#dob date,
#photo nvarchar(150),
#secq int,
#secAnswer nvarchar(150),
#completed int output)
as
declare #found int
/*
usertype:
0 - Administrator
1 - User
*/
begin
begin
select #found=count(*) from registration r
where REPLACE(r.firstname,' ','')=REPLACE(#fName,' ','')
and REPLACE(r.lastname,' ','')=REPLACE(#lname,' ','')
and r.dateofbirth=#dob;
end
begin
if #found=0
begin
begin
insert into Login values(#userID,#pw,0,1);
end
begin
insert into registration values(
#userID,#fName,#lname,#email,
#address,#city,#country,#phone,
#gender,#dob,#photo,#secq,#secAnswer
)
end
begin
set #completed=1;
end
end
else set #completed=0
end
return #completed
end
And here is the exec:
DECLARE #return_value int,
#completed int
SELECT #completed = 0
EXEC #return_value = [dbo].[sp_addUser]
#userID = N'a',
#pw = N'a',
#fName = N'a',
#lname = N'a',
#email = N'a',
#address = N'a',
#city = 1,
#country = 1,
#phone = N'a',
#gender = N'a',
#dob = '01/01/2000',
#photo = N'a',
#secq = 1,
#secAnswer = N'a',
#completed = #completed OUTPUT
SELECT #completed as N'#completed'
SELECT 'Return Value' = #return_value
Thanks in advance!
sp_adduser is a procedure which is built-in to SQL Server - see https://msdn.microsoft.com/en-us/library/ms181422.aspx
Don't use the sp_ prefix for your own stored procedures, maybe call it proc_adduser instead, I think that will work
You are actually calling the system stored procedure sp_adduser. The "sp_" prefix is special and has its own rules on resolution, so using it is recommended against. If you want to use your own prefix, whatever you do, don't use "sp_".
Per #marc_s, even if your stored procedure doesn't clash with an existing system stored procedure, you will still get a noticeable performance hit due to cache misses.

Return one OUTPUT result from MERGE query

I have a merge query which updates or inserts if no records found. In my results, I have a problem when the record does not exist and it get inserted. The query returns BOTH 'Updated' (as empty) and 'Inserted' (with the proper value).
Any ideas how to avoid return the empty 'Updated' when there are no updates?
ALTER PROCEDURE [dbo].[spInsOrUpdApplicant]
-- Add the parameters for the stored procedure here
#Name nvarchar(50),
#Surname nvarchar(50),
#Position nvarchar(50),
#NationalID int,
#ApplicantID int
AS
BEGIN
SET NOCOUNT ON;
-- Update the row if it exists.
UPDATE tbApplicant
SET Name = #Name, Surname = #Surname, Position = #Position, NationalID = #NationalID
OUTPUT INSERTED.ApplicantID AS 'Result'
WHERE ApplicantID = #ApplicantID;
-- Insert the row if the UPDATE statement failed.
IF (##ROWCOUNT = 0 )
BEGIN
INSERT INTO tbApplicant (Name, Surname, Position, NationalID)
OUTPUT INSERTED.ApplicantID AS 'Result'
VALUES (#Name, #Surname, #Position, #NationalID)
END
END;
It seems that the 'output' always fires even if no actual rows were updated. You can see the same behavior in triggers. You might want to consider doing the following:
ALTER PROCEDURE [dbo].[spInsOrUpdApplicant]
-- Add the parameters for the stored procedure here
#Name nvarchar(50),
#Surname nvarchar(50),
#Position nvarchar(50),
#NationalID int,
#ApplicantID int
AS
BEGIN
SET NOCOUNT ON;
-- Check if the row exists.
IF EXISTS (SELECT 1 FROM tbApplicant WHERE ApplicantID = #ApplicantID) BEGIN
-- update if the row exists.
UPDATE tbApplicant
SET Name = #Name, Surname = #Surname, Position = #Position, NationalID = #NationalID
OUTPUT INSERTED.ApplicantID AS 'Result'
WHERE ApplicantID = #ApplicantID;
END
ELSE BEGIN
-- Else Insert.
INSERT INTO tbApplicant (Name, Surname, Position, NationalID)
OUTPUT INSERTED.ApplicantID AS 'Result'
VALUES (#Name, #Surname, #Position, #NationalID)
END
END;
I do something very similar.
Inside my stored procedure, I have this:
DECLARE #mergeResults TABLE (mergeAction varchar(10), tableName varchar(50));
OUTPUT $action, 'Table Name' INTO #mergeResults;
Can you insert into the table variable and then decide how you want to move the data based on what you see?
You mentioned you have a merge query but you aren't using a merge - you're using more of an "upsert".
Merge T-SQL: http://msdn.microsoft.com/en-us/library/bb510625.aspx

how to late parameter bind to dynamic sql statement in a stored procedure

I am attempting to dynamically build a T-SQL statement based on a FieldMapping table and some business rules.
Cut the long story short, I have a function that will return the SQL statement as a varchar(max) that I will execute as EXEC (#Sql) in my stored procedure.
Allow me to demonstrate with a test table
create procedure [dbo].[sp_TestInsert]
(
#Id int,
#Name varchar(20),
#Surname varchar(20),
#Age int,
#Source varchar(1)
)
as
declare #sql varchar(max)
-- Return SQL statement that depends on business rules
-- i.e. if the #Source = 'i' the returned SQL will be:
-- "update TestTable set Name = #Name, Surname = #Surname, SONbr = #SONbr WHERE Id = #Id"
-- however if the #Source = 'a' the returned SQL will be
-- "update TestTable set Name = #Name, Surname = #Surname, SONbr = #SONbr, Age = #Age WHERE Id = #Id"
-- As you can see, in case of 'i', it will NOT return Age = #Age
set #sql = dbo.func_UpdateOrInsert('TestTable', #Source)
-- When this statement is executed, the error I get is 'scalar #Name does not exist'
exec (#sql)
I've commented on the operation.
The problem is obvious, I would have expected that #Id, #Name, #Surname etc... would bind automatically to the corresponding field names [Id], [Name], [Surname] etc in the context of the stored procedure... however, this is not the case.
Is there any way I can bind the parameters to a dynamically built SQL statement?
The sp_executesql stored procedure does this
create procedure [dbo].[sp_TestInsert]
#Id int,
#Name varchar(20),
#Surname varchar(20),
#Age int,
#Source varchar(1)
as
declare
#sql nvarchar(max) = dbo.func_UpdateOrInsert('TestTable', #Source),
#params nvarchar(max)
= N'#Name varchar(20), #Surname varchar(20), #SONbr int, #Age int'
-- You need to get #SONbr from somewhere
exec sp_executesql #sql, #params, #Name, #Surname, #SONbr, #Age
-- note, it doesn't matter if a bound parameter isn't mentioned in the query
-- so #Age can be passed in regardless.

SQL Trigger not firing

I Update the table and the Trigger doesn't fire. Or at least it doesn't seem to insert into the other table the information. Is there something I may be missing in my code?
ALTER TRIGGER [dbo].[UpdateUsers]
ON [VLS_TEST].[dbo].[Identifier]
AFTER UPDATE
AS
DECLARE #Status VARCHAR(4)
DECLARE #License_Nbr VARCHAR(9)
DECLARE #Email VARCHAR (100)
DECLARE #FName VARCHAR(15)
DECLARE #LName VARCHAR(25)
SELECT #Status = Status,
#License_Nbr = License_Nbr,
#Email = Email,
#FName = FName,
#LName = LName
FROM VLS_Test.dbo.Identifier
IF ( #Status = 'LISC'
AND ( #License_Nbr LIKE '__01%'
OR #License_Nbr LIKE '__06%' ) )
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
IF NOT EXISTS (SELECT *
FROM RTT_DEV.dbo.Users
WHERE RTT_DEV.dbo.Users.TerminalOperatorNum = #License_Nbr)
BEGIN
INSERT INTO RTT_DEV.dbo.Users
(Username,
PASSWORD,
UserType,
TerminalOperatorNum,
AdminName,
FirstName,
LastName)
VALUES (#Email,
'********',
'2',
#License_Nbr,
'System',
#FName,
#LName)
END
END