I have this stored procedure:
CREATE PROCEDURE [dbo].[AddEmployee]
(
#employeeId int OUTPUT,
#firstName varchar(50),
#lastName varchar(50),
#password varchar(100)
)
AS
BEGIN
INSERT INTO Employees(FirstName, LastName)
VALUES(#firstName, #lastName)
INSERT INTO Logins(Password, EmployeeId)
VALUES(#password, #employeeId)
SELECT ##Identity
END
GO
Let,
#employeeId = EmployeeId
generated during insert in Employees
After that, I was trying to insert the #employeeId into the Logins table.
Also, the #employeeId is used as OUTPUT parameter.
How should I do it?
May be we can use INSERTED.EmployeeId, but I don't know how to use it.
CREATE PROCEDURE [dbo].[AddEmployee] (
#firstName VARCHAR(50)
, #lastName VARCHAR(50)
, #password VARCHAR(100)
, #employeeId INT OUTPUT
)
AS
BEGIN
INSERT INTO Employees (
FirstName
, LastName
)
VALUES (
#firstName
, #lastName
)
SELECT #employeeId = SCOPE_IDENTITY()
INSERT INTO Logins (
Password
, EmployeeId
)
VALUES (
#password
, #employeeId
)
END
GO
EXEC [dbo].[AddEmployee] #firstname = 'test'
, #lastname = 'tester'
, #password = '321321'
, #employeeId = ''
Assuming your EmployeeId column is an IDENTITY column, you should use the OUTPUT clause to fetch the value (you output it into a table variable):
DECLARE #empId TABLE (empId int)
INSERT INTO Employees
(
FirstName, LastName
)
OUTPUT INSERTED.EmployeeId INTO #empId
VALUES
(
#firstName,
#lastName
)
Then to get the value from the table variable into a scalar variable, do:
SET #employeeId = (SELECT TOP 1 empId FROM #empId)
The ##Identity value is the last identity inserted in the current session regardless of scope. Hence, it could be the identity of a row inserted by a trigger. It's always better to use scope_identity() instead. For more details, see MSDN.
You can assign an output parameter like:
set #employeeId = scope_identity()
Related
I am using SQL Server 2017. It has SP which inserts data into table passed via parameters.
create table employee(
id int,
first_name varchar(100),
last_name varchar(100),
salary int,
city varchar(100)
)
Create PROCEDURE MasterInsertUpdateDelete
(
#id INTEGER,
#first_name VARCHAR(10),
#last_name VARCHAR(10),
#salary INTEGER,
#city VARCHAR(20),
#StatementType nvarchar(20) = ''
)
AS
BEGIN
IF #StatementType = 'Insert'
BEGIN
insert into employee (id,first_name,last_name,salary,city) values( #id, #first_name, #last_name, #salary, #city)
END
IF #StatementType = 'Select'
BEGIN
select * from employee
END
END
Suppose I execute SP using below statement
exec MasterInsertUpdateDelete
#id = 1,
#first_name = 'Vijay',
#last_name = 'Kumar',
#salary = 100,
#city = 'Pune',
#StatementType = 'Insert'
Now I want to capture original query (replace with parameter values) which is being executed on DB server
i.e. insert into employee (id,first_name,last_name,salary,city) values( 1, 'Vijay', 'Kumar', 100, 'Test')
I used SQL profiler and exended events but it gives me SQL statement along with parameters
i.e.
insert into employee (id,first_name,last_name,salary,city) values( #id, #first_name, #last_name, #salary, #city)
Practically I have more complex store procedure as Dynamic SQL. I would like to capture the executing statement with replace variable values. How can we achieve it in MS SQL Server?
I created a stored procedure but when I tried to use it I got error.
"Msg 8114, Level 16, State 5, Procedure SP_Customer_Add, Line 0 [Batch
Start Line 36] Error converting data type varchar to
uniqueidentifier."
alter proc SP_Customer_Add (
#UserID uniqueidentifier,
#Firstname nvarchar(30),
#Surname nvarchar(30),
#CardNumber nvarchar(16),
#Password nvarchar(4),
#City nvarchar(13),
#Birthdate smalldatetime,
#Email nvarchar(30),
#PhoneNumber nvarchar (10),
#Balance money
)
as
begin
set nocount on;
insert into Customers (
[UserID],
[Firstname],
[Surname],
[CardNumber],
[Password],
[City],
[Birthdate],
[Email],
[PhoneNumber],
[Balance]
) values (
#UserID,
#Firstname,
#Surname,
#CardNumber,
#Password,
#City,
#Birthdate,
#Email ,
#PhoneNumber ,
#Balance
)
select #UserID = newID();
END
I call the procedure like:
exec SP_Customer_Add
'Cem',
'Yücel',
'1234567891234567',
'1111','Malatya',
'1999/12/5',
'Cemyucel#yahoo.com',
'5421234312',
10000
If you're inserting rows with a GUID, then let the RDBMS handle the generation. I assume that the ID is also the CLUSTERED INDEX so change it so that it has a default value:
ALTER TABLE dbo.Customers ADD CONSTRAINT DF_UserID DEFAULT NEWSEQUENTIALID() FOR UserID;
Then DROP your SP and recreate it with the name Customer_Add (because having the prefix is a problem, as my comment says) and recreate the SP without any references to UserID as a variable or to INSERT.
Your are not passing a value for the parameter (#UserID) when calling the procedure SP_Customer_Add
exec SP_Customer_Add
'Cem',
'Yücel',
'1234567891234567',
'1111','Malatya',
'1999/12/5',
'Cemyucel#yahoo.com',
'5421234312',
10000
Below is the altered procedure:
alter proc SP_Customer_Add
(
#Firstname nvarchar(30),
#Surname nvarchar(30),
#CardNumber nvarchar(16),
#Password nvarchar(4),
#City nvarchar(13),
#Birthdate smalldatetime,
#Email nvarchar(30),
#PhoneNumber nvarchar (10),
#Balance money
)
as
begin
set nocount on;
DECLARE #UserID uniqueidentifier
SET #UserID = NEWID()
insert into Customers ([UserID],[Firstname], [Surname], [CardNumber], [Password], [City], [Birthdate], [Email], [PhoneNumber], [Balance] )
values
(
#UserID,
#Firstname,
#Surname,
#CardNumber,
#Password,
#City,
#Birthdate,
#Email ,
#PhoneNumber ,
#Balance
)
END
Let's say I have have the following parameters:
#firstName varchar(50), #middleName varchar(50), #LastName varchar(50)
I want the middle name to be optional, How do I return the value (#portalUserName) without middle name if the middle name is not passed as an input parameter?
PS: I need the middle names first character to be added in the user name if the user has a middle name (i.e. if middle name value isn't null)
CREATE PROCEDURE [dbo].[cst_sproc_UserName_Get]
(#firstName VARCHAR(50),
#middleName VARCHAR(50),
#LastName VARCHAR(50)
)
AS
BEGIN
DECLARE #portalUserName VARCHAR(50)
SET #portalUserName = SUBSTRING(UPPER(RTRIM(#firstname)), 1, 1) +
SUBSTRING(UPPER(RTRIM(#firstname)), 1, 1) +
LOWER(RTRIM(#LastName))
IF NOT EXISTS (SELECT 'TRUE' FROM wpUser WHERE UserCode = #portalUserName)
BEGIN
SELECT #portalUserName UserCode
RETURN
END
END
To make a parameter optional, you need to give it a default value, which could be NULL.
CREATE PROC [dbo].[cst_sproc_UserName_Get]
(
#firstName varchar(50),
#middleName varchar(50) = NULL,
#LastName varchar(50)
)
AS
BEGIN
Declare #portalUserName varchar(50)
SET #portalUserName = SUBSTRING(upper(RTRIM(#firstname)),1,1)+ SUBSTRING(upper(RTRIM(#firstname)),1,1) + lower(RTRIM(#LastName))
IF NOT EXISTS (SELECT 'TRUE' FROM wpUser WHERE UserCode = #portalUserName)
BEGIN
SELECT #portalUserName UserCode
Return
END
But to call it, you need to follow Best Practices and call your procedure with parameter naming.
EXEC [dbo].[cst_sproc_UserName_Get] #firstName = 'Luis', #LastName = 'Cazares';
I am trying to create procedure, which is generating an error stating
An explicit value for the identity column in table tblRegisterUser can only be specified when a column list is used and IDENTITY_INSERT is ON.
I tried to surround insert statement with INDENTITY_INSERT to ON,but that too doesn't work. am I missing anything or is it an error with the sub query which i included?
Following is the stored procedure
CREATE PROCEDURE dbo.spInsertUserRegister
(
#FirstName nvarchar(50),
#LastName nvarchar(50),
#Username nvarchar(50),
#Password nvarchar(50),
#Designation nvarchar(50),
#Department nvarchar(50),
#IsAdmin bit
)
AS
BEGIN
INSERT INTO tblRegisterUser Values
(
#FirstName, #LastName, #Username, #Password,#Designation,#Department,#IsAdmin
)
DECLARE #UID INT
SET #UID = ##IDENTITY
INSERT INTO tblLogin(Username,Password,UID,IsAdmin)
Values(#Username, #Password, #UID,(SELECT IsAdmin FROM tblRegisterUser WHERE Username=#Username AND Password=#Password))
END
If the structure of the tblRegisterUser table is something like
ID int primary_key autoincrement
FirstName varchar
LastName varchar
Username varchar
Password varchar
Designation varchar
Department varchar
IsAdmin bit
than this statement is wrong:
INSERT INTO tblRegisterUser Values
(
#FirstName, #LastName, #Username, #Password,
#Designation,#Department,#IsAdmin
)
You should use an explicit column list to specify the columns:
INSERT INTO tblRegisterUser
( FirstName, LastName, Username, Password,
Designation, Department, IsAdmin)
VALUES
(
#FirstName, #LastName, #Username, #Password,
#Designation,#Department,#IsAdmin
)
This way the ID field is automatically populated, and the ##Identity statement should return it correctly.
That said, SQL Server has a few functions that return the generated ID for the last rows, each with it's own specific strengths and weaknesses.
Basically:
##IDENTITY works if you do not use triggers
SCOPE_IDENTITY() works for the code you explicitly called.
IDENT_CURRENT(‘tablename’) works for a specific table, across all scopes.
In almost all scenarios SCOPE_IDENTITY() is what you need, and it's a good habit to use it, opposed to the other options.
A good discussion on the pros and cons of the approaches is also available here.
copied from this answer
Try this one -
CREATE PROCEDURE dbo.spInsertUserRegister
(
#FirstName NVARCHAR(50),
#LastName NVARCHAR(50),
#Username NVARCHAR(50),
#Password NVARCHAR(50),
#Designation NVARCHAR(50),
#Department NVARCHAR(50),
#IsAdmin BIT
)
AS BEGIN
INSERT INTO dbo.tblRegisterUser (FirstName, LastName, Username, [Password], Designation, Department, IsAdmin)
SELECT #FirstName, #LastName, #Username, #Password, #Designation, #Department, #IsAdmin
DECLARE #ID BIGINT
SELECT #ID = SCOPE_IDENTITY()
--SET IDENTITY_INSERT dbo.tblLogin ON;
INSERT INTO dbo.tblLogin (UserName, [password], [uid], IsAdmin)
SELECT #Username, #Password, #ID, IsAdmin
FROM tblRegisterUser
WHERE UserName = #Username
AND [password] = #Password
--SET IDENTITY_INSERT dbo.tblLogin OFF;
END
I have a stored procedure that creates a user profile, my form has the following fields:
FirstName,
LastName.
EmailAddress,
ZipCode,
Password
The zip code is a FK in my UserProfile of type smallint the value may or may not already exist in a table called Location:
LocationId bigInt (identity index)
ZipCode smallint
Is there a way from within my stored procedure to query that table, if the item exist use the PK of that entry in my stored procedure ?
This is my stored procedure so far
CREATE PROCEDURE [dbo].[SP_InsertInitialProfile]
#FirstName NVARCHAR(1000),
#LastName NVARCHAR(1000),
#EmailAddress NVARCHAR(1000),
#ZipCode SMALLINT,
#Password NVARCHAR(1000)
AS
IF (SELECT COUNT(1) FROM UserProfile WHERE EmailAddress =#EmailAddress) = 1
BEGIN
RETURN -1
END ELSE
BEGIN
INSERT INTO UserProfile(FirstName,LastName,EmailAddress,Password)
VALUES(#FirstName,#LastName,#EmailAddress,#Password)
RETURN Cast(##IDENTITY as INT)
END
You can do SP like this:
CREATE PROCEDURE [dbo].[SP_InsertInitialProfile]
#FirstName NVARCHAR(1000),
#LastName NVARCHAR(1000),
#EmailAddress NVARCHAR(1000),
#ZipCode SMALLINT,
#Password NVARCHAR(1000)
AS
varCountNbr number;
BEGIN
SELECT COUNT(1) INTO varCountNbr
FROM
Location
WHERE
ZipCode=#ZipCode;
IF varCountNbr = 0
INSERT #ZipCode INTO Location TABLE;
-- You have to commit here, in order to have the PK value exists.
COMMIT;
INSERT INTO USERPROFILE TABLE;
COMMIT;
END;