I am currently working in C#, and I need to insert a new record into one table, get the new primary key value, and then use that as a foreign key reference in inserting several more records. The Database is MS SQL Server 2003. All help is appreciated!
-
Are you using a framework like LINQ or are you using SQL string queries ? (in my answer i'm assuming LINQ) – Yona Nov 25 '08 at 00:34
3 Answers
The way to get the identity of the inserted row is with the SCOPE_IDENTITY()
function. If you're using stored procedures then this would look something like the following to return the row identity as an output parameter.
CREATE PROCEDURE dbo.MyProcedure
(
@RowId INT = NULL OUTPUT
)
AS
INSERT INTO MyTable
(
Column1
,Column2
,...
)
VALUES
(
@Param1
,@Param2
,...
);
SET @RowId = SCOPE_IDENTITY();
You can then use this value for any subsequent inserts (alternatively, if you can pass the data all into the stored procedure, then you can use it in the remainder of the procedure body).
If you're passing the SQL in dynamically then you use much the same technique, but with a single string with statement delimiters (also ;
in SQL), e.g.:
var sql = "INSERT INTO MyTable (Column1, Column2, ...) VALUES (@P1, @P2, ...);" +
"SELECT SCOPE_IDENTITY();";
Then if you execute this using ExecuteScalar
you'll be able to get the identity back as the scalar result and cast it to the right type. Alternatively you could build up the whole batch in one go, e.g.
var sql = "DECLARE @RowId INT;" +
"INSERT INTO MyTable (Column1, Column2, ...) VALUES (@P1, @P2, ...);" +
"SET @RowId = SCOPE_IDENTITY();" +
"INSERT INTO MyOtherTable (Column1, ...) VALUES (@P3, @P4, ...);";
This may not be exactly the right syntax, and you may need to use SET NOCOUNT ON;
at the start (my mind is rusty as I rarely use dynamic SQL) but it should get you on the right track.

- 133,383
- 43
- 204
- 250
-
I prefer this method (using OUT parameters) over returning a dataset. Expecially for auto generated code. – Robert Wagner Nov 25 '08 at 00:32
-
-
I prefer output parameters as I think they're more self-documenting than scalar result sets, but either way would work fine. – Greg Beech Nov 25 '08 at 01:08
The best way of doing this is the use SCOPE_IDENTITY() function in TSQL. This should be executed as part of the insert i.e.
SqlCommand cmd = new SqlCommand(@"
INSERT INTO T (Name) VALUES(@Name)
SELECT SCOPE_IDENTITY() As TheId", conn);
cmd.AddParameter("@Name", SqlDbType.VarChar, 50).Value = "Test";
int tId = (int)cmd.ExecuteScalar();
Alternatively you can assign SCOPE_IDENTITY() to a variable to be used in successive statements. e.g.
DECLARE @T1 int
INSERT INTO T (Name) VALUES('Test')
SELECT @T1 = SCOPE_IDENTITY()
INSERT INTO T2 (Name, TId) VALUES('Test', @T1)

- 2,493
- 2
- 17
- 13
-
Are all those one string, or passed in as separate strings? Your solution doesn't make that clear. Remember, I'm doing SQL queries via C#. – Zeroth Nov 25 '08 at 00:31
-
In both instances you could pass one string. For the first method you could use the SqlCommand ExecuteScaler() to get the identity of the row just inserted. You would also want to bind the hardcoded 'Test' to a @Name parameter using command.AddParameter to avoid sql injection. – Duncan Nov 25 '08 at 00:36
If you are just using SQL then check Duncan's answer. If however you are using LINQ then you can create the entity, save it to the DB and the ID parameter will be populated automatically.
Given a user entity and a user table it might look like this:
using(var db = new DataContext()) {
var user = new User { Name = "Jhon" };
db.Users.InsertOnSubmit(user);
db.SubmitChanges();
/* At this point the user.ID field will have the primary key from the database */
}

- 9,392
- 4
- 33
- 42
-
this is linq to sql, linq to entities or dbcontext. Just in case someone dint realize that... – hidden Nov 20 '11 at 20:15