Return IDENT_CURRENT which was inserted - c#

I have INSERT INTO SqlCommand and I need to display after INSERT INTO the IDENT_CURRENT which was inserted with these values
SqlCommand sc = new SqlCommand("INSERT INTO kliplat (datum,text,castka,akce,subkey,priznak,rocnik) values (#datum,#text,#castka,#akce,#subkey,#priznak,#rocnik)", spojeni);
spojeni.Open();
sc.Parameters.AddWithValue("#subkey", vyber_id_kli);
sc.Parameters.AddWithValue("#akce", vyberakce);
sc.Parameters.AddWithValue("#priznak", vyberplat);
sc.Parameters.AddWithValue("#datum", maskedTextBox1.Text);
sc.Parameters.AddWithValue("#text", textBox1.Text);
sc.Parameters.AddWithValue("#castka", textBox2.Text);
sc.Parameters.AddWithValue("#rocnik", rocnik);
sc.ExecuteReader();
spojeni.Close();
This IDENT_CURRENT is: INTEGER IDENTITY PRIMARY KEY
Now I was dealing with this issue like this:
SqlCommand comm = new SqlCommand("SELECT IDENT_CURRENT ('mytable')", conn);
spojeni.Open();
int max = Convert.ToInt32(comm.ExecuteScalar());
spojeni.Close();
But I found out that this is extremely hazardous to do.
Thank you all for your time reading this.

You could use a command that returns the newly inserted id:
SqlCommand sc = new SqlCommand(#"
INSERT INTO kliplat (datum,text,castka,akce,subkey,priznak,rocnik)
VALUES (#datum,#text,#castka,#akce,#subkey,#priznak,#rocnik);
SELECT scope_identity();
", spojeni);
...
var newIdentity = (long) sc.ExecuteScalar();

I think you may consider using scope_identity() function instead of ident_current.
SCOPE_IDENTITY, IDENT_CURRENT, and ##IDENTITY are similar functions
because they return values that are inserted into identity columns.
IDENT_CURRENT is not limited by scope and session; it is limited to a
specified table. IDENT_CURRENT returns the value generated for a
specific table in any session and any scope. For more information, see
IDENT_CURRENT (Transact-SQL). SCOPE_IDENTITY and ##IDENTITY return the
last identity values that are generated in any table in the current
session. However, SCOPE_IDENTITY returns values inserted only within
the current scope; ##IDENTITY is not limited to a specific scope.

Assuming your field is called ID; add this to your query:
OUTPUT INSERTED.ID
And catch the result in your c# code

Related

I'm having some issues with my scope identity retrieving a ID from an identity column

I'm having some issues with my scope identity retrieving a ID from an identity column.
This is my code:
cmd = connection.CreateCommand();
cmd.CommandText = "Insert Into oc_manufacturer (name, sort_order) Values(#name, #sort_order);SELECT CAST(scope_identity() AS int)";
cmd.Parameters.AddWithValue("#name", sManufacturer);
cmd.Parameters.AddWithValue("#sort_order", 0);
iManufacturerID = (int)cmd.ExecuteScalar();
cmd.ExecuteNonQuery();
This is inside a try catch. and it hits my catch when i step through it at the 2nd last line of code. I am still very new to using this scope identity. Usually i would create a whole new select statement with the same variables as my insert statement. But that is very long so truing to get this right. any help?
Perhaps I am wrong, but you have marked your question as MySql. In that database system, you retrieve the last inserted autoincrement value with LAST_INSERT_ID() function
cmd.CommandText = #"Insert Into oc_manufacturer (name, sort_order)
Values(#name, #sort_order);
SELECT LAST_INSERT_ID()";
Also there is no need to call ExecuteNonQuery, the call to ExecuteScalar will work on both statements but will return the value of the last SELECT

Executing an insert statement and put id in a local variable?

SqlDataSource myQuiz = new SqlDataSource();
myQuiz.ConnectionString = ConfigurationManager.ConnectionStrings["yafnet"].ToString();
myQuiz.InsertCommand = "INSERT INTO [QuizTable]([Quiz_Title],[Quiz_Description]) VALUES (#Quiz_Title,#Quiz_Description)";
myQuiz.InsertParameters.Add("Quiz_Title",Quiz_Title.Text);
myQuiz.InsertParameters.Add("Quiz_Description",Quiz_Description.Text);
myQuiz.Insert();
Response.Redirect("QuizQuests.aspx");
Is there a way to get back the automatically generated ID of the new row and put it in a local variable?
Thanks a lot in advance,
Adrian
Use
SELECT IDENT_CURRENT(‘QuizTable’)
It returns the last IDENTITY value produced in a table, regardless of the connection that created the value, and regardless of the scope of the statement that produced the value.
IDENT_CURRENT is not limited by scope and session; it is limited to a specified table. IDENT_CURRENT returns the identity value generated for a specific table in any session and any scope.
If you want to be 100% sure that you really get the identity from your insert in your actual QuizTable, you should use SCOPE_IDENTITY() (as already mentioned by Luiggi Mendoza in his comment), and not ##IDENTITY or IDENT_CURRENT.
##IDENTITY might not work because it will return the identity from the last insert that happened from your connection. So if there is a trigger on your QuizTable which inserts a row in another table that has an identity column as well, ##IDENTITY will return the value from that second insert, and not that of the original insert into the QuizTable .
IDENT_CURRENT will return the last identity value for your table (and only for your table, so it doesn't matter if there are triggers like the one in the previous example).
But it returns the last identity value for any session. So if another row is inserted from another session between your INSERT and your IDENT_CURRENT, you'll get the identity value from that row, not from yours.
#Adrian De Barro: hi you can use following code to get inserted record id and save in variable
in your sqlquery add following statement:
return ##IDENTITY
and your C# code will be as follows:
SqlConnection cn = new
SqlConnection(ConfigurationManager.AppSettings["ConnectionString"]);
cn.Open();
SqlCommand cmd = new SqlCommand(procname, cn);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter str = new SqlParameter("name", SqlDbType.VarChar);
str.Direction = ParameterDirection.ReturnValue;
foreach (SqlParameter par in param)
{
cmd.Parameters.Add(par);
}
string name = Convert.ToString(cmd.ExecuteScalar());
cmd.Dispose();
cn.Close();
return name;

How can i get the ##IDENTITY returned from a INSERT from MySQL (2008) using C# [duplicate]

Using C# in Visual Studio, I'm inserting a row into a table like this:
INSERT INTO foo (column_name)
VALUES ('bar')
I want to do something like this, but I don't know the correct syntax:
INSERT INTO foo (column_name)
VALUES ('bar')
RETURNING foo_id
This would return the foo_id column from the newly inserted row.
Furthermore, even if I find the correct syntax for this, I have another problem: I have SqlDataReader and SqlDataAdapter at my disposal. As far as I know, the former is for reading data, the second is for manipulating data. When inserting a row with a return statement, I am both manipulating and reading data, so I'm not sure what to use. Maybe there's something entirely different I should use for this?
SCOPE_IDENTITY returns the last identity value inserted into an identity column in the same scope. A scope is a module: a stored procedure, trigger, function, or batch. Therefore, two statements are in the same scope if they are in the same stored procedure, function, or batch.
You can use SqlCommand.ExecuteScalar to execute the insert command and retrieve the new ID in one query.
using (var con = new SqlConnection(ConnectionString)) {
int newID;
var cmd = "INSERT INTO foo (column_name)VALUES (#Value);SELECT CAST(scope_identity() AS int)";
using (var insertCommand = new SqlCommand(cmd, con)) {
insertCommand.Parameters.AddWithValue("#Value", "bar");
con.Open();
newID = (int)insertCommand.ExecuteScalar();
}
}
try this:
INSERT INTO foo (column_name)
OUTPUT INSERTED.column_name,column_name,...
VALUES ('bar')
OUTPUT can return a result set (among other things), see: OUTPUT Clause (Transact-SQL). Also, if you insert multiple values (INSERT SELECT) this method will return one row per inserted row, where other methods will only return info on the last row.
working example:
declare #YourTable table (YourID int identity(1,1), YourCol1 varchar(5))
INSERT INTO #YourTable (YourCol1)
OUTPUT INSERTED.YourID
VALUES ('Bar')
OUTPUT:
YourID
-----------
1
(1 row(s) affected)
I think you can use ##IDENTITY for this, but I think there's some special rules/restrictions around it?
using (var con = new SqlConnection("connection string"))
{
con.Open();
string query = "INSERT INTO table (column) VALUES (#value)";
var command = new SqlCommand(query, con);
command.Parameters.Add("#value", value);
command.ExecuteNonQuery();
command.Parameters.Clear();
command.CommandText = "SELECT ##IDENTITY";
int identity = Convert.ToInt32(command.ExecuteScalar());
}

Return value from SQL Server Insert command using c#

Using C# in Visual Studio, I'm inserting a row into a table like this:
INSERT INTO foo (column_name)
VALUES ('bar')
I want to do something like this, but I don't know the correct syntax:
INSERT INTO foo (column_name)
VALUES ('bar')
RETURNING foo_id
This would return the foo_id column from the newly inserted row.
Furthermore, even if I find the correct syntax for this, I have another problem: I have SqlDataReader and SqlDataAdapter at my disposal. As far as I know, the former is for reading data, the second is for manipulating data. When inserting a row with a return statement, I am both manipulating and reading data, so I'm not sure what to use. Maybe there's something entirely different I should use for this?
SCOPE_IDENTITY returns the last identity value inserted into an identity column in the same scope. A scope is a module: a stored procedure, trigger, function, or batch. Therefore, two statements are in the same scope if they are in the same stored procedure, function, or batch.
You can use SqlCommand.ExecuteScalar to execute the insert command and retrieve the new ID in one query.
using (var con = new SqlConnection(ConnectionString)) {
int newID;
var cmd = "INSERT INTO foo (column_name)VALUES (#Value);SELECT CAST(scope_identity() AS int)";
using (var insertCommand = new SqlCommand(cmd, con)) {
insertCommand.Parameters.AddWithValue("#Value", "bar");
con.Open();
newID = (int)insertCommand.ExecuteScalar();
}
}
try this:
INSERT INTO foo (column_name)
OUTPUT INSERTED.column_name,column_name,...
VALUES ('bar')
OUTPUT can return a result set (among other things), see: OUTPUT Clause (Transact-SQL). Also, if you insert multiple values (INSERT SELECT) this method will return one row per inserted row, where other methods will only return info on the last row.
working example:
declare #YourTable table (YourID int identity(1,1), YourCol1 varchar(5))
INSERT INTO #YourTable (YourCol1)
OUTPUT INSERTED.YourID
VALUES ('Bar')
OUTPUT:
YourID
-----------
1
(1 row(s) affected)
I think you can use ##IDENTITY for this, but I think there's some special rules/restrictions around it?
using (var con = new SqlConnection("connection string"))
{
con.Open();
string query = "INSERT INTO table (column) VALUES (#value)";
var command = new SqlCommand(query, con);
command.Parameters.Add("#value", value);
command.ExecuteNonQuery();
command.Parameters.Clear();
command.CommandText = "SELECT ##IDENTITY";
int identity = Convert.ToInt32(command.ExecuteScalar());
}

How to insert a record and return the newly created ID using a single SqlCommand?

I'm using an SqlCommand object to insert a record into a table with an autogenerated primary key. How can I write the command text so that I get the newly created ID when I use the ExecuteScalar() method?
INSERT INTO YourTable(val1, val2, val3 ...)
VALUES(#val1, #val2, #val3...);
SELECT SCOPE_IDENTITY();
Don't forget the semicolons at the end of each statement.
Add the following line to the end of the Sql Query...
SELECT SCOPE_IDENTITY()
And then use the ExecuteScalar method on the SqlCommand object...
var rowCount = command.ExecuteScalar()
insert into Yourtable()
values()
SELECT SCOPE_IDENTITY()
I just ran a test and verified that the semi-colons are optional using SQL Server 2005 SP2, and .Net 3.5
Add an output parameter to the command object and then set the value to the new ID in the stored procedure.
Stored Procedure:
#ID AS INT OUTPUT
[Insert Command]
SET #ID = SCOPE_IDENTITY()
.NET:
cmd.CommandText = "stored_procedure";
SqlParameter pID = new SqlParameter("ID", DBType.Int32, 4);
pID.Direction = ParameterDirection.Output;
cmd.ExecuteScalar();
int id = Convert.ToInt32(cmd.Parameters["ID"].Value.ToString());
Don't use ##IDENTITY, however simple it may seem. It can return incorrect values.
SELECT SCOPE_IDENTITY()
appears to be the obvious choice.
Although I like Dave Markle's answer, ( and I see you did too, since you marked it as your answer ), that method can fail if you have triggers on your database, that audit CUD operations, and your audit table has an IDENTITY column. It would return the value of the Audit table's identity, not the table you just inserted into, since the audit table actualy happen after.
In that case, a more generic method can be used that will work in both cases, regardless of any auditing. Its a bit more wordy, but you get what you pay for.
example:
#"DECLARE #tmp AS TABLE ( id int )
INSERT INTO case
(
caseID,
partID,
serialNumber,
hardware,
software,
firmware
)
OUTPUT Inserted.ID into #tmp
VALUES
(
#caseID,
#partItemID,
#serialNumber,
#hardware,
#software,
#firmware
)
Select ID from #tmp" )
Immediately after your insert stmt, use
SELECT CAST(scope_identity() AS bigint) ---- incase you have a return result as int64
This will return the column created id/identity.
If your id is a Guid, then I found this solution to be best:
INSERT INTO YourTable (val1, val2, val3)
OUTPUT inserted.id
VALUES (#val1, #val2, #val3)
Thanks #Scott Ivey
Full demo:
internal static Guid InsertNote(Note note)
{
Guid id;
using (
var connection =
new SqlConnection(ConfigurationManager.ConnectionStrings["dbconn"].ConnectionString))
{
connection.Open();
using (
var command =
new SqlCommand(
"INSERT INTO Notes ([Title],[Text]) " +
"OUTPUT inserted.id " +
$"VALUES ('{title}','{text}');", connection))
{
command.CommandType = CommandType.Text;
var reader = command.ExecuteReader();
reader.Read();
id = reader.GetGuid(reader.GetOrdinal("id"));
}
connection.Close();
}
return id;
}
I would recommend using a Stored Procedure, but this is for unit testing our repository.
Straight out of the Whirlpool:
If you're using MS SQL you can use "SELECT ##IDENTITY as Value" after your insert to get the last ID generated
and:
##IDENTITY and SCOPE_IDENTITY return the last identity value generated in any table in the current session. However, SCOPE_IDENTITY returns the value only within the current scope; ##IDENTITY is not limited to a specific scope.
Edit: As pointed out in the comments, you should always use SCOPE_IDENTITY, not ##IDENTITY.

Categories