I am inserting a row into one table then want to get that new ID so I can add it in another variable where I have email address stored.
var db = Database.Open("myDB");
var insertCommand1 = "INSERT INTO myDB (FirstName, LastName) Values(#0, #1)";
db.Execute(insertCommand1, first, last);
var lastInsertedId = db.QueryValue("SELECT SCOPE_IDENTITY()");
var insertCommand2 = "INSERT INTO email (id_person, email) Values(#0, #1)";
db.Execute(insertCommand2, lastInsertId, email);
where id_person is the id that is created in my first table. When I run the code I get lastInsertedId = {}. Any reason why it is not grabbing a value for id_person which is a primary key, int , not null for my first table? --Tim
From the documentation of SCOPE_IDENTITY(), emphasis mine:
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.
Because you are using two queries they are considered two batches. You need to do your insert and your select in a single query.
I don't know what library you are using, so I am just guessing on the syntax but I beleive you need something like
var db = Database.Open("myDB");
var insertCommand1 = "INSERT INTO myDB (FirstName, LastName) Values(#0, #1); " +
"SELECT SCOPE_IDENTITY()";
var lastInsertedId = db.QueryValue(insertCommand1, first, last);
var insertCommand2 = "INSERT INTO email (id_person, email) Values(#0, #1)";
db.Execute(insertCommand2, lastInsertId, email);
It is very easy to get the SCOPE_IDENTITY() value back from SQL Server. I will give an example where I was able to print the SCOPE_IDENTITY() data back in c# label.
My Code Snippet in a Submit from data insert
btnSubmit_Click()
{
Random s = new Random();
cmd = new SqlCommand("INSERT INTO [dbo].[tblMemberAccount] ([Userid], [User_pwd], [User_mobile], [User_referal], [UserWallet]) VALUES(#Userid, #User_pwd, #User_mobile, #User_referal, #UserWallet) select scope_identity()", cons);
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("#Userid",s.Next(4506,9999));
cmd.Parameters.AddWithValue("#User_pwd",txtPassword.Text);
cmd.Parameters.AddWithValue("#User_mobile",txtPhoneNumber.Text);
cmd.Parameters.AddWithValue("#User_referal",txtReferral.Text);
cmd.Parameters.AddWithValue("#UserWallet",10);
cons.Open();
int g = Convert.ToInt32(cmd.ExecuteScalar());
cons.Close();
lblConfirm.Text = "Member " +g+ " added successfully!";
}
Here the value 'g' is returning the scope_identity value.
If the database is in SQL SERVER , create a SQL parameter and set the direction to
"Output".
Please check this link :
Getting the identity of the most recently added record
Related
There is a syntax problem on Asp.Net when I try to run an insert on a table if I have a vlaue in another table that I look for.
I tried different queries and datareaders but that generates a problem, one of the 2 datareaders needs to be closed.
con.Open();
String insertRegInfo = "INSERT INTO Login (NumEmp,Nombre,Apellido,Codigo) values (#NumEmp, #Nombre,#Apellido,#Codigo) SELECT NumEmp from Empleados WHERE NumEmp = " + TxtNumEmp.Text +"" ;
MySqlCommand command = new MySqlCommand(insertRegInfo, con);
LblConfirm.Text = "Confirmado";
command.Parameters.AddWithValue("#NumEmp", TxtNumEmp.Text);
command.Parameters.AddWithValue("#Nombre", TxtNombre.Text);
command.Parameters.AddWithValue("#Apellido", TxtApellido.Text);
command.Parameters.AddWithValue("#Codigo", TxtCodigo.Text);
command.ExecuteNonQuery();
con.Close();
I expect to insert data into the table if any value is true.
Let me start saying that this is a terrible coding practice:
String insertRegInfo = "INSERT INTO Login (NumEmp,Nombre,Apellido,Codigo) values (#NumEmp, #Nombre,#Apellido,#Codigo) SELECT NumEmp from Empleados WHERE NumEmp = " + TxtNumEmp.Text +"" ;
Better is:
String insertRegInfo = "INSERT INTO Login (NumEmp,Nombre,Apellido,Codigo)
SELECT NumEmp,#Nombre,#Apellido,#Codigo from Empleados WHERE NumEmp = #NumEmp" ;
You should use parameters instead and better even Store Procedures.
However, to answer your question. All you need to do is match the number of columns of your SQL Command.
INSERT INTO Login (NumEmp,Nombre,Apellido,Codigo)
SELECT NumEmp, #Nombre,#Apellido,#Codigo from Empleados WHERE…
Note that I removed the values section from the insert. That is not required
Is there a way to retrieve the latest inserted guid in access with C#?
I tried this: Created a table Cars with a field Id of type autonumber, replicationID and a field Name varchar(250).
var command = myConnection.CreateCommand();
command.Connection.Open();
command.CommandText = "INSERT INTO Cars(Name) VALUES ('Pagani')";
command.ExecuteNonQuery();
command = context.Database.Connection.CreateCommand();
command.CommandText = "SELECT ##Identity";
Console.WriteLine(command.ExecuteScalar());
command.Connection.Close();
The issue which I am getting is:
Console.WriteLine(command.ExecuteScalar());
always shows 0
EDIT
To create the table you can use this statement over the C# OleDb connection (I think that from MS Access query does not work)
CREATE TABLE [Cars] (
[Id] guid not null DEFAULT GenGUID(),
[Name] text null
);
ALTER TABLE [Cars] ADD CONSTRAINT [PK_Cars_6515ede4] PRIMARY KEY ([Id])
I know this is not exactly what you are asking for, but let me suggest an alternative solution which might solve your underlying problem.
Create the GUID in C# and pass it to your insert:
var newGuid = Guid.NewGuid();
var command = myConnection.CreateCommand();
command.Connection.Open();
command.CommandText = "INSERT INTO Cars(Id, Name) VALUES (?, 'Pagani')";
command.Parameters.AddWithValue("#Id", newGuid); // Note: OleDb ignores the parameter name.
command.ExecuteNonQuery();
Console.WriteLine(newGuid);
GUIDs are unique. It really doesn't matter whether it is generated by your application or by the Access database driver.
This option is in all respects superior to reading the GUID afterwards:
You only need one database access.
It's less code.
It's easier.
And you can still omit the GUID in your INSERT in cases where you don't need to know the GUID - no need to change existing code.
If SELECT ##IDENTITY does not work for "ReplicationID" AutoNumber fields then the most likely way to retrieve such a value for a new record is to use an Access DAO Recordset insert, like this:
// required COM reference:
// Microsoft Office 14.0 Access Database Engine Object Library
var dbe = new Microsoft.Office.Interop.Access.Dao.DBEngine();
Microsoft.Office.Interop.Access.Dao.Database db = dbe.OpenDatabase(
#"C:\Users\Public\Database1.accdb");
Microsoft.Office.Interop.Access.Dao.Recordset rst = db.OpenRecordset(
"SELECT [Id], [Name] FROM [Cars] WHERE FALSE",
Microsoft.Office.Interop.Access.Dao.RecordsetTypeEnum.dbOpenDynaset);
rst.AddNew();
// new records are immediately assigned an AutoNumber value ...
string newReplId = rst.Fields["Id"].Value; // ... so retrieve it
// the returned string is of the form
// {guid {1D741E80-6847-4CB2-9D96-35F460AEFB19}}
// so remove the leading and trailing decorators
newReplId = newReplId.Substring(7, newReplId.Length - 9);
// add other field values as needed
rst.Fields["Name"].Value = "Pagani";
// commit the new record
rst.Update();
db.Close();
Console.WriteLine("New record added with [Id] = {0}", newReplId);
which produces
New record added with [Id] = 1D741E80-6847-4CB2-9D96-35F460AEFB19
You can try like this using the OUTPUT :
INSERT INTO myTable(myGUID)
OUTPUT INSERTED.myGUID
VALUES(GenGUID())
You can try like this:
string str1 = "INSERT INTO Cars(Name) VALUES ('Pagani')";
string str2 = "Select ##Identity";
int ID;
using (OleDbConnection conn = new OleDbConnection(connect))
{
using (OleDbCommand cmd = new OleDbCommand(str1, conn))
{
conn.Open();
cmd.ExecuteNonQuery();
cmd.CommandText = str2;
ID = (int)cmd.ExecuteScalar();
}
}
I'm having a simple problem but cant find a solution:
I'm creating a row in my table client, but I don't know how recovery the id of the table that I just created, for example:
ALTER proc [dbo].[spinsert_client]
#idclient int output,
#name varchar(20),
#surname varchar(40),
as
insert into client(name,surname)
values (#name,#surname)
here I insert a client, now I want recovery that exact same idclient to insert "products" with it without have to manually search this client , I tried recovering the last row of the client table but I realise that if more than one person is using the same database in different computers it can be a problem, so I need create a client and recovery his id at the same time (it is an assumption I don't know). Im using sql server and Visual studio with c#
sorry for my bad English and thanks for the attention
edit-------------------
solution:
ALTER proc [dbo].[spinsert_client]
#idclient int output,
#name varchar(20),
#surname varchar(40)
as
insert into client(name,surname)
values (#name,#surname)
Select ##IDENTITY as newId;
them in my c# code:
rpta= SqlCmd.ExecuteScalar().ToString();
The best way is to use the OUTPUT clause. Here is an example that just captures the new id:
ALTER proc [dbo].[spinsert_client] (
#idclient int output,
#name varchar(20),
#surname varchar(40)
)
as
begin
declare #output table (idclient int);
insert into client(name, surname)
output inserted.idclient into #output;
values (#name, #surname);
select *
from #output;
end; -- spinsert_client
In your C# code you have somewhere a sql Statement defined:
string sqlStatement = "INSERT INTO ... (field list) OUTPUT INSERTED.yourfieldwithid values (value list) ";
and use it with ExecuteScalar() for getting the result value (I assume you know how to use Connection and command object)
You can do this:
string query = "INSERT INTO client" +
" (name, surname)" +
" VALUES (#Name, #Surname);" +
" SELECT SCOPE_IDENTITY();";
using (var dbconn = new SqlConnection("your connection string here") )
using (var dbcm = new SqlCommand(query, dbconn) )
{
dbcm.Parameters.Add("#Name", SqlDbType.VarChar, 20).Value = "name value";
dbcm.Parameters.Add("#Surname", SqlDbType.VarChar, 40).Value = "surname value";
dbconn.Open();
var insertedID = (int)dbcm .ExecuteScalar();
}
Check this SO post explaining every way of retrieving the inserted id from the table.
To answer your question, both OUTPUT_CLAUSE and IDENT_CURRENT can be used in this scenario but i would recomment IDENT_CURRENT because an OUTPUT clause will return rows to the client even if the statement encounters errors and is rolled back.
Use it like:
using (SqlCommand com = new SqlCommand("INSERT INTO cient(name, surname)"+
"VALUES (#Name, #Surname) SELECT IDENT_CURRENT('client'); ", con))
I would not suggest SCOPE_IDENTITY or ##IDENTITY because it may return wrong values (null) if you're not using SQL Server 2008 R2 SP2 or higher ( source - last row from the page.) especially for your requirement (inserting the value in some other table).
I iterate over an external source and get a list of strings. I then insert them into the DB using:
SqlCommand command = new SqlCommand(commandString, connection);
command.ExecuteNonQuery();
Where commandString is an insert into command. i.e.
insert into MyTable values (1, "Frog")
Sometimes the string contains ' or " or \ and the insert fails.
Is there an elegant way to solve this (i.e. #"" or similar)?
Parameters.
insert into MyTable values (#id, #name)
And
int id = 1;
string name = "Fred";
SqlCommand command = new SqlCommand(commandString, connection);
command.Parameters.AddWithValue("id", id);
command.Parameters.AddWithValue("name", name);
command.ExecuteNonQuery();
Now name can have any number of quotes and it'll work fine. More importantly it is now safe from sql injection.
Tools like "dapper" (freely available on NuGet) make this easier:
int id = 1;
string name = "Fred";
connection.Execute("insert into MyTable values (#id, #name)",
new { id, name });
You should look into using parameterized queries. This will allow you insert the data no matter the content and also help you avoid possible future SQL injection.
http://csharp-station.com/Tutorial/AdoDotNet/Lesson06
http://www.c-sharpcorner.com/uploadfile/puranindia/parameterized-query-and-sql-injection-attacks/
I'm working on an ASP.NET project (C#) with SQL Server 2008.
When I insert a row into a table in the database, I would like to get the last inserted ID, which is the table's IDENTITY (Auto Incremented).
I do not wish to use another query, and do something like...
SELECT MAX(ID) FROM USERS;
Because - even though it's only one query - it feels lame...
When I insert something I usually use ExecuteNonQuery(), which returns the number of affected rows.
int y = Command.ExecuteNonQuery();
Isn't there a way to return the last inserted ID without using another query?
Most folks do this in the following way:
INSERT dbo.Users(Username)
VALUES('my new name');
SELECT NewID = SCOPE_IDENTITY();
(Or instead of a query, assigning that to a variable.)
So it's not really two queries against the table...
However there is also the following way:
INSERT dbo.Users(Username)
OUTPUT inserted.ID
VALUES('my new name');
You won't really be able to retrieve this with ExecuteNonQuery, though.
You can return the id as an output parameter from the stored procedure, e.g. #userId int output
Then, after the insert, SET #userId = scope_identity()
even though it's only one query - it feels lame...
It actually is also wrong as you can have multiple overlapping iserts.
That is one thing that I always fuind funny - people not reading the documentation.
SELECT SCOPE_IDENTITY()
returns the last identity value generated in a specific scope and is syntactically correct. It also is properly documented.
Isn't there a way to return the last inserted ID without using another query?
Yes. Ask for the number in the saame SQL batch.
INSERT (blablab9a); SELECT SCOPE_IDENTITY ();
as ONE string. ExecuteScalar.
You can have more than one SQL statement in one batch.
If you want to execute query from C# code & want to get last inserted id then you have to find the following code.
SqlConnection connection = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
connection.Open();
string sql = "Insert into [Order] (customer_id) values (" + Session["Customer_id"] + "); SELECT SCOPE_IDENTITY()";
SqlCommand cmd = new SqlCommand();
cmd.Connection = connection;
cmd.CommandText = sql;
cmd.CommandType = CommandType.Text;
var order_id = cmd.ExecuteScalar();
connection.Close();
Console.Write(order_id);