Related
This question already has answers here:
How to get last inserted id?
(16 answers)
Closed 5 years ago.
How to display the id after inserting the data with the use of stored procedure, my sample stored procedure is like this..
CREATE PROCEDURE [dbo].[insertResidence]
#Fname varchar(50),
#Lname varchar(50),
#Mname varchar(50),
#Bdate varchar(50),
#BirthPlace varchar(50),
#CivStat varchar(50),
#Purok varchar(50),
#Religion varchar(50),
#Gender varchar(50),
#CitShip varchar(50)
AS
Begin tran one;
Declare #resId INT;
INSERT INTO [tbl_Residence] (resFname, resLname, resMname, resBdate, resBirthPlace, resGender) VALUES (#Fname,#Lname,#Mname,#Bdate,#BirthPlace,#Gender);
Select #resId = SCOPE_IDENTITY();
NSERT INTO [tbl_Religion] (resId, religion) VALUES (#resId,#Religion);
INSERT INTO [tbl_Purok] (resId,pur_sit) VALUES (#resId,#Purok);
INSERT INTO [tbl_Citizenship] (resId,citship) VALUES (#resID,#Purok);
Select resId from tbl_Residence WHERE resId = #resId;
commit tran;
RETURN
After inserting the data I want to display the id in the label or textboxt.
I use ExecuteNonQuery() in the transaction..
This is the code of inserting data in transaction
public int insertRes(Informations info)
{
//Insert Residence Informations
SqlCommand cmd = new SqlCommand("InsertResidence");
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#FName", SqlDbType.VarChar).Value = info.Fname;
cmd.Parameters.AddWithValue("#LName", SqlDbType.VarChar).Value = info.Lname;
cmd.Parameters.AddWithValue("#MName", SqlDbType.VarChar).Value = info.Mname;
cmd.Parameters.AddWithValue("#BDate", SqlDbType.VarChar).Value = info.Bdate;
cmd.Parameters.AddWithValue("#BirthPlace", SqlDbType.VarChar).Value = info.BirthPlace;
cmd.Parameters.AddWithValue("#CivStat", SqlDbType.VarChar).Value = info.CivStat;
cmd.Parameters.AddWithValue("#Purok", SqlDbType.VarChar).Value = info.purok;
cmd.Parameters.AddWithValue("#Religion", SqlDbType.VarChar).Value = info.Religion;
cmd.Parameters.AddWithValue("#Gender", SqlDbType.VarChar).Value = info.Gender;
cmd.Parameters.AddWithValue("#CitShip", SqlDbType.VarChar).Value = info.CitShip;
return db.ExeNonQuery(cmd);
}
UI layer :
Business layer:
ExecuteNonQuery will only return you the number of rows effected by your command.
Use ExecuteScalar, which will return you resId.
To display:
int resId = (int)cmd.ExecuteScalar();
Then in your UI:
lblMyLabel.Text = resId.ToString();
I'm new in c#,and want to write simple application work with sql server store procedure,in the sql server write this store procedure:
USE [mammutRecruitment]
ALTER PROCEDURE [dbo].[FirstStep]
#Name nvarchar(max),#Family nvarchar(max),#FatherName nvarchar(max),#BirthCertificate bigint,#PlaceOfBirth nvarchar(max),#BirthDate datetime,
#NationalCode bigint,#Religion nvarchar(max),#faith nvarchar(max),#Nationality nvarchar(max),#BloodGroup nvarchar(max)
AS
BEGIN
DECLARE #MYID bigint
insert into [dbo].[UserMainSpecifications] values(#Name,#Family,#FatherName,#BirthCertificate,#PlaceOfBirth,1,#BirthDate,#NationalCode,
#Religion,#faith,#Nationality,#BloodGroup,12,'123','123',1,2015-1-1,'12','123','1234',1)
select #MYID=[UserID] from [mammutRecruitment].[dbo].[UserMainSpecifications]
where [NationalCode]=#NationalCode
select #MYID as myID
END
and in c# write this code for call that:
using (SqlConnection con = new SqlConnection("Data Source=.;Initial Catalog=mammutRecruitment;Integrated Security=True"))
{
using (SqlCommand cmd = new SqlCommand("FirstStep", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#Name", SqlDbType.NVarChar).Value = m.Name;
cmd.Parameters.Add("#Family", SqlDbType.NVarChar).Value = m.Family;
cmd.Parameters.Add("#FatherName", SqlDbType.NVarChar).Value = m.FatherName;
cmd.Parameters.Add("#BirthCertificate", SqlDbType.BigInt).Value =Convert.ToInt64(m.BirthCertificate);
cmd.Parameters.Add("#PlaceOfBirth", SqlDbType.NVarChar).Value = m.PlaceOfBirth;
cmd.Parameters.Add("#BirthDate", SqlDbType.DateTime).Value =Convert.ToDateTime(dt.ToString());
cmd.Parameters.Add("#NationalCode", SqlDbType.BigInt).Value =Convert.ToInt64(m.NationalCode);
cmd.Parameters.Add("#Religion", SqlDbType.NVarChar).Value = m.Religion;
cmd.Parameters.Add("#faith", SqlDbType.NVarChar).Value = m.faith;
cmd.Parameters.Add("#Nationality", SqlDbType.NVarChar).Value = m.Nationality;
cmd.Parameters.Add("#BloodGroup", SqlDbType.NVarChar).Value = m.BloodGroup;
SqlParameter retval = cmd.Parameters.Add("#myID", SqlDbType.BigInt);
retval.Direction = ParameterDirection.ReturnValue;
con.Open();
cmd.ExecuteNonQuery();
var retunvalue = cmd.Parameters["#myID"].Value;
but in the this line i get zero value always:
var retunvalue = cmd.Parameters["#myID"].Value;
What happen?How can i solve that problem?thanks.
This line:
cmd.ExecuteNonQuery();
Is executing your query and not returning a value.
You could start by looking into using this instead:
cmd.ExecuteReader();
Or if you want the value of the first field of the first row, you could use this:
var returnValue = cmd.ExecuteScalar();
Which will give you an object that you can then convert or cast into the appropriate type for your method.
SqlCommand.ExecuteNonQuery Method ()
Executes a Transact-SQL statement against the connection and returns
the number of rows affected.
SqlCommand.ExecuteScalar Method ()
Executes the query, and returns the first column of the first row in
the result set returned by the query. Additional columns or rows are
ignored.
I believe you want the second method
You need to include #myID as an output parameter in your stored procedure definition:
ALTER PROCEDURE [dbo].[FirstStep]
#Name nvarchar(max),#Family nvarchar(max),#FatherName nvarchar(max),#BirthCertificate bigint,#PlaceOfBirth nvarchar(max),#BirthDate datetime,
#NationalCode bigint,#Religion nvarchar(max),#faith nvarchar(max),#Nationality nvarchar(max),#BloodGroup nvarchar(max)
, #myID bigint output
AS
And then remove the line
DECLARE #MYID bigint
You also need to add the parameter to cmd in your c# code:
cmd.Parameters.Add(retval);
you need define #MYID as output parameter.
USE [mammutRecruitment]
ALTER PROCEDURE [dbo].[FirstStep]
#MYID bigint output,#Name nvarchar(max),#Family nvarchar(max),#FatherName nvarchar(max),#BirthCertificate bigint,#PlaceOfBirth nvarchar(max),#BirthDate datetime,
#NationalCode bigint,#Religion nvarchar(max),#faith nvarchar(max),#Nationality nvarchar(max),#BloodGroup nvarchar(max)
AS
BEGIN
insert into [dbo].[UserMainSpecifications] values(#Name,#Family,#FatherName,#BirthCertificate,#PlaceOfBirth,1,#BirthDate,#NationalCode,
#Religion,#faith,#Nationality,#BloodGroup,12,'123','123',1,2015-1-1,'12','123','1234',1)
select #MYID = SCOPE_IDENTITY()
END
and add your command
SqlParameter pOut = new SqlParameter("#MYID", SqlDbType.BigInt);
pOut.Direction = ParameterDirection.Output;
cmd.Parameters.Add(pOut);
You can read the value now
cmd.ExecuteNonQuery();
long newId = (long)pOut.Value;
Actually, you need change that statement:
retval.Direction = ParameterDirection.ReturnValue;
to
retval.Direction = ParameterDirection.Output
because ExecuteNonQuery return:
Executes a Transact-SQL statement against the connection and returns the number of rows affected.
Although the ExecuteNonQuery returns no rows, any output parameters or return values mapped to parameters are populated with data.
End include your parameter to procedure definition:
#myID BIGINT OUTPUT
USE [mammutRecruitment]
ALTER PROCEDURE [dbo].[Firststep] #Name NVARCHAR(max),
#Family NVARCHAR(max),
#FatherName NVARCHAR(max),
#BirthCertificate BIGINT,
#PlaceOfBirth NVARCHAR(max),
#BirthDate DATETIME,
#NationalCode BIGINT,
#Religion NVARCHAR(max),
#faith NVARCHAR(max),
#Nationality NVARCHAR(max),
#BloodGroup NVARCHAR(max),
#myID BIGINT output
AS
BEGIN
INSERT INTO [dbo].[usermainspecifications]
VALUES (#Name,
#Family,
#FatherName,
#BirthCertificate,
#PlaceOfBirth,
1,
#BirthDate,
#NationalCode,
#Religion,
#faith,
#Nationality,
#BloodGroup,
12,
'123',
'123',
1,
2015 - 1 - 1,
'12',
'123',
'1234',
1)
SELECT #myID = [userid]
FROM [mammutRecruitment].[dbo].[usermainspecifications]
WHERE [nationalcode] = #NationalCode
END
So I'm trying to learn how to use stored procedures and for the most part I somewhat understand how to use them except for this merge procedure.
What I'm trying to do is use the MERGE procedure to Insert if a row does not already exist and return the ID ELSE IF NOT EXISTS then just return the ID.
Here is currently what I have so far.
CREATE PROCEDURE dbo.authors_InsertOrUpdate
-- Add the parameters for the stored procedure here
#FirstName nvarchar(50),
#LastName nvarchar(50),
#id int = NULL OUTPUT
AS
MERGE Authors AS target
USING (SELECT #FirstName, #LastName) AS source (FirstName, LastName)
ON target.FirstName = source.FirstName AND target.LastName = source.LastName
WHEN MATCHED THEN
UPDATE
SET #id = SCOPE_IDENTITY()
WHEN NOT MATCHED THEN INSERT
(FirstName, LastName) VALUES (source.FirstName, source.LastName);
SET #id = SCOPE_IDENTITY()
Everything works fine as far as inputting the values/information into the database and finding an existing one but I'm not getting my ID value back correctly. Here is my method that uses it..
private static int storeAuthors(string firstName, string lastName)
{
String commandText = "dbo.authors_InsertOrUpdate";
using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["AmazonCrawler.Properties.Settings.database"].ToString()))
{
using (SqlCommand command = new SqlCommand(commandText, connection))
{
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("#FirstName", firstName));
command.Parameters.Add(new SqlParameter("#LastName", lastName));
SqlParameter authorId = new SqlParameter("#id", SqlDbType.Int);
authorId.Direction = ParameterDirection.Output;
command.Parameters.Add(authorId);
connection.Open();
command.ExecuteNonQuery();
connection.Close();
return Convert.ToInt32(authorId.Value);
}
}
}
Please help me fix this!
Thanks in advance.
---------EDIT------------
Updated the procedure to this yet I'm still receiving a null value in my code when i try to return the value
CREATE PROCEDURE dbo.authors_InsertOrUpdate
-- Add the parameters for the stored procedure here
#FirstName nvarchar(50),
#LastName nvarchar(50),
#id int OUTPUT
AS
MERGE Authors AS target
USING (SELECT #id, #FirstName, #LastName) AS source (id, FirstName, LastName)
ON target.FirstName = source.FirstName AND target.LastName = source.LastName
WHEN NOT MATCHED THEN
INSERT (FirstName, LastName) VALUES (source.FirstName, source.LastName);
SET #id = SCOPE_IDENTITY()
Edit reference 1
Edit reference 2
Edit reference 3
ALTER PROCEDURE dbo.authors_InsertOrUpdate
-- Add the parameters for the stored procedure here
#FirstName nvarchar(50),
#LastName nvarchar(50),
#id int OUTPUT
AS
MERGE Authors AS target
USING (SELECT #id, #FirstName, #LastName) AS source (ID, FirstName, LastName)
ON target.FirstName = source.FirstName AND target.LastName = source.LastName
WHEN MATCHED THEN
UPDATE SET #id = target.ID
WHEN NOT MATCHED THEN
INSERT (FirstName, LastName) VALUES (source.FirstName, source.LastName);
SET #id = SCOPE_IDENTITY()
SELECT #id
Still receiving same error listed in reference 2.
=( no solution yet.
here is my passed in values with a return of zero as an id
and here is my database
Edit reference 4
Tried changing my parameters when putting in the values to this as I thought perhaps closing it before getting the value was causing the problem but no luck
private static int storeAuthors(string firstName, string lastName)
{
String commandText = "dbo.authors_InsertOrUpdate";
using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["AmazonCrawler.Properties.Settings.database"].ToString()))
{
using (SqlCommand command = new SqlCommand(commandText, connection))
{
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("#FirstName", firstName));
command.Parameters.Add(new SqlParameter("#LastName", lastName));
SqlParameter authorId = new SqlParameter("#id", SqlDbType.Int);
authorId.Direction = ParameterDirection.Output;
command.Parameters.Add(authorId);
connection.Open();
command.ExecuteNonQuery();
int value = Convert.ToInt32(authorId.Value);
connection.Close();
return value;
}
}
}
In the UPDATE case, you aren't generating a new IDENTITY, you are just querying, so SCOPE_IDENTITY() won't return the right value. In the UPDATE case, SCOPE_IDENTITY() may appear to work, at first, but it is actually returning the value from the last INSERT in scope (I think), which could be the last execution of the stored proc.
I recommend using the OUTPUT clause. I tried to make something work with your approach, and with #usr's suggestion as well, but the only thing I could make work was to use the OUTPUT clause. See below:
CREATE PROCEDURE dbo.authors_InsertOrUpdate
-- Add the parameters for the stored procedure here
#FirstName nvarchar(50),
#LastName nvarchar(50),
#id int OUTPUT
AS BEGIN
DECLARE #MergeOutput table
(
ACTION VARCHAR(10),
ID INT
);
MERGE Authors AS target
USING (SELECT #id, #FirstName, #LastName) AS source (id, FirstName, LastName)
ON target.FirstName = source.FirstName AND target.LastName = source.LastName
WHEN NOT MATCHED THEN
INSERT (FirstName, LastName) VALUES (source.FirstName, source.LastName)
WHEN MATCHED THEN UPDATE
SET #Id = target.Id
OUTPUT $action, INSERTED.ID INTO #MergeOutput;
SELECT #Id = Id FROM #MergeOutput
END
GO
DECLARE #id2 INT
exec dbo.authors_InsertOrUpdate 'Melvin', 'Smith', #id = #id2 OUTPUT
SELECT #id2
GO
I tried to make something work using SCOPE_IDENTITY(), and using SET #Id = target.Id as in #usr's answer but I kept getting the last inserted value returned, even for an update.
SELECT * INTO #o FROM sys.objects
DECLARE #id INT
MERGE #o AS target
USING (SELECT OBJECT_ID('tempdb..#o') AS object_id) AS source (object_id)
ON target.object_id = source.object_id
WHEN MATCHED THEN UPDATE SET #id = target.object_id;
SELECT #id
You can use columns of the MERGE query pretty freely. It is a very powerful statement.
I am using VS 2008 Asp.net C#. To insert the data I have created a stored procedure:
ALTER PROCEDURE INS_tblRegister
#Enroll varchar,
#Name varchar,
#Dob varchar,
#Gender varchar,
#Mobile varchar,
#Address varchar,
#Branch varchar,
#Sem varchar,
#Year varchar,
#Password varchar
AS
INSERT INTO tblRegister (Enrollment, Name, Dob, Gender, Mobile, Address, Branch, Sem, Year, Password)
VALUES (#Enroll,#Name,#Dob,#Gender,#Mobile,#Address,#Branch,#Sem,#Year,#Password)
RETURN
Below is my code for button_Click :
try
{
con.Open();
cmd = new SqlCommand("INS_tblRegister",con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#Enroll", SqlDbType.VarChar).Value = txtEnroll.Text;
cmd.Parameters.Add("Name", SqlDbType.VarChar).Value = txtName.Text;
cmd.Parameters.Add("Dob", SqlDbType.VarChar).Value = (txtDob.Text);
cmd.Parameters.Add("Gender", SqlDbType.VarChar).Value = ddlGender.Text;
cmd.Parameters.Add("Mobile", SqlDbType.VarChar).Value = txtMobile.Text;
cmd.Parameters.Add("Address", SqlDbType.VarChar).Value = txtAddress.Text;
cmd.Parameters.Add("Branch", SqlDbType.VarChar).Value = txtBranch.Text;
cmd.Parameters.Add("Sem", SqlDbType.VarChar).Value = txtSem.Text;
cmd.Parameters.Add("Year", SqlDbType.VarChar).Value = txtYear.Text;
cmd.Parameters.Add("Password", SqlDbType.VarChar).Value = txtPassword.Text;
cmd.ExecuteNonQuery();
con.Close();
lblMsg.Text="Saved";
}
catch(Exception ex)
{
lblMsg.Visible = true;
lblMsg.Text = ex.Message;
}
This code was executed successfully but when I see the database I found :
Only the first character of my entry saved eg: look at the Gender field,I wrote Male but only M is inserted to database. Please Help me...
The default length for CHAR and VARCHAR is 1.
char and varchar (Transact-SQL)
You need to define the length of VARCHAR in the Signature
#MyField VARCHAR(100)
You need to add character lengths to your stored procedure parameters like this:
ALTER PROCEDURE INS_tblRegister
#Enroll varchar(20),#Name varchar(20),#Dob varchar(20),#Gender varchar(20),#Mobile varchar(20),#Address varchar(20), #Branch varchar(20), #Sem varchar(20), #Year varchar(20), #Password varchar(20)
AS
INSERT INTO tblRegister (Enrollment, Name, Dob, Gender, Mobile, Address, Branch, Sem, Year, Password)
VALUES (#Enroll,#Name,#Dob,#Gender,#Mobile,#Address,#Branch,#Sem,#Year,#Password)
RETURN
Declare variables of SP as #Enroll varchar(size), where size is int value. Example#Enroll varchar(500). The varchar will only consider first character since its length is 1.
Provide length of each varchar field.
ALTER PROCEDURE INS_tblRegister
#Enroll varchar(10),#Name varchar(50),
#Dob varchar(10),#Gender varchar(6),#Mobile varchar(10),#Address varchar(100),
etc...
You need to mention the size of varchar. Try this procedure.
ALTER PROCEDURE INS_tblRegister
#Enroll varchar(50),#Name varchar(50), #Dob varchar(50), #Gender varchar(50), #Mobile varchar(50), #Address varchar(50),
#Branch varchar(50), #Sem varchar(50), #Year varchar(50), #Password varchar(50)
AS
INSERT INTO tblRegister(Enrollment, Name, Dob, Gender, Mobile, Address, Branch, Sem, Year, Password) VALUES(#Enroll,#Name,#Dob,#Gender,#Mobile,#Address,#Branch,#Sem,#Year,#Password)
RETURN
The default varchar size is 1 character.
varchar[(n)]
When n is not specified in a data definition or variable declaration statement, the default length is 1.
ALTER PROCEDURE INS_tblRegister
#Enroll varchar(20),#Name varchar(20),#Dob varchar(20),#Gender varchar(20),#Mobile varchar(20),#Address varchar(20), #Branch varchar(20), #Sem varchar(20), #Year varchar(20), #Password varchar(20)
AS
INSERT INTO tblRegister (Enrollment, Name, Dob, Gender, Mobile, Address, Branch, Sem, Year, Password)
VALUES (#Enroll,#Name,#Dob,#Gender,#Mobile,#Address,#Branch,#Sem,#Year,#Password)
RETURN
I am using ASP.NET 4.0, C# and SQL Server 2008 R2. I am getting UserName from the user in a webpage for stored in the SQL table User_Info2. Using SQL Server 2008 feature "computed column" I am generating the Vendor_ID automatically for every Insert using the stored procedure. In button click, after I insert the record I want to display the message with Vendor_ID, so please anyone tell me how to get the Vendor_ID column from the stored procedure ?
CREATE TABLE User_Info2
( SNo int Identity (2000,1) ,
Vendor_ID AS 'VEN' + CAST(SNo as varchar(16)) PERSISTED PRIMARY KEY,
UserName VARCHAR(30) NOT NULL
)
Stored procedure
ALTER PROCEDURE [dbo].[usp_User_Info2] #UserName VARCHAR(30)
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO User_Info2 (UserName) VALUES (#UserName)
END
C# Code :
protected void BtnUserNext_Click(object sender, EventArgs e)
{
SqlConnection SqlCon = new SqlConnection(GetConnectionString());
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "usp_User_Info2";
cmd.Parameters.Add("#UserName", SqlDbType.VarChar).Value = txtUserName.Text.Trim();
cmd.Connection = SqlCon;
try
{
SqlCon.Open();
cmd.ExecuteScalar();
}
finally
{
string url = "../CompanyBasicInfo.aspx?Parameter=" + Server.UrlEncode ("+ Vendor_ID +");
ClientScript.RegisterStartupScript(this.GetType(),"callfunction",
"alert('Login created successfully for "+ Vendor_ID +"');
window.location.href = '" + url + "';", true);
SqlCon.Close();
}
}
You can output the inserted value using the OUTPUT clause, and then read it when you execute the stored procedure:
ALTER PROCEDURE [dbo].[usp_User_Info2] #UserName VARCHAR(30)
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO User_Info2 (UserName)
OUTPUT Inserted.Vendor_ID
VALUES (#UserName)
END
and in your C# calling code:
object spResult;
string vendorID;
try
{
SqlCon.Open();
spResult = cmd.ExecuteScalar();
if(spResult != null) // check to make sure you got something back!
{
vendorID = spResult.ToString();
}
}
You can try this
ALTER PROCEDURE [dbo].[usp_User_Info2] #UserName VARCHAR(30)
AS
BEGIN
SET NOCOUNT ON;
declare #Id int
INSERT INTO User_Info2 (UserName) VALUES (#UserName)
SET #Id = Scope_Identity()
SELECT Vendor_ID From User_Info2 WHERE SNo = #Id
END
C#
try
{
SqlCon.Open();
string VendorID = cmd.ExecuteScalar() as string;
}
Also u can do like this
select top(1) Vendor_ID from User_Info2 order by SNo desc
You can get currently insert row with the help of SCOPE_IDENTITY()
SET #SNo = SCOPE_IDENTITY()
And below insert query you can execute select query on the #SNo
So it would be:
ALTER PROCEDURE [dbo].[usp_User_Info2]
(
#UserName VARCHAR(30),
#SNo int,
#Vendor_ID VARCHAR(50) OUTPUT
)
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO User_Info2 (UserName) VALUES (#UserName)
SET #SNo = Scope_Identity()
select #Vendor_ID as Vendor_ID from User_Info2 where SNo = #SNo
END
EDIT:
SqlParameter[] param= new SqlParameter[1];
param[0] = new SqlParameter("#Vendor_ID", 0);
param[0].Direction = ParameterDirection.Output;
// Here there will be a Stored Procedure Call
int VendorID = Convert.ToInt32(param[0].Value);
So now you will #Vendor_ID which is an Output variable.