March 31, 2011 by Christoff Truter SQL
Retrieving the last inserted identity(ID) on a table is a very common task when working with pretty
much any relational database. There are a number of ways to do this, most of these "ways" are unfortunately
potentially dangerous and must be avoided if possible.
Instead of simply giving you definitions on some of these methods, lets take a more practical approach in
order to see the potential pitfalls (it also makes for a longer post at least, hehe).
Firstly we're going to create two tables (for now at least) for testing purposes:
CREATE TABLE [dbo].[x] ( [xID] [int] IDENTITY(1,1) NOT NULL, [ID] [uniqueidentifier] NOT NULL, CONSTRAINT [PK_x] PRIMARY KEY CLUSTERED ( [xID] ASC )) GO CREATE TABLE [dbo].[y] ( [yID] [int] IDENTITY(1,1) NOT NULL, [xID] [int] NOT NULL, [ID] [uniqueidentifier] NOT NULL, CONSTRAINT [PK_y] PRIMARY KEY CLUSTERED ( [yID] ASC )) GO
CREATE PROCEDURE [dbo].[Test] AS BEGIN DECLARE @xID INT, @ID UNIQUEIDENTIFIER SET @ID = NEWID() INSERT INTO x(ID) VALUES(@ID) --SET @xID = -- Some Retrieval Method INSERT INTO y(xID, ID) VALUES(@xID, @ID) END
select count(*) from x join y on x.xID = y.xID and x.ID = y.ID
using System.Data.SqlClient; using System.Configuration; using System.Threading; class Program { static void Main(string[] args) { for (int i = 0; i < 10; i++) { new Thread(() => { using (SqlConnection connection = new SqlConnection("some connection")) { connection.Open(); using (SqlCommand command = new SqlCommand("Test", connection)) { command.CommandType = System.Data.CommandType.StoredProcedure; command.ExecuteNonQuery(); } } }).Start(); } } }
SET @xID = @@IDENTITY
CREATE TABLE [dbo].[z]( [zID] [int] IDENTITY(1,1) NOT NULL, [xID] [int] NOT NULL, [ID] [uniqueidentifier] NOT NULL, CONSTRAINT [PK_z] PRIMARY KEY CLUSTERED ( [zID] ASC )) CREATE TRIGGER [dbo].[triggerHappy] ON [dbo].[x] AFTER INSERT AS INSERT INTO z(xID, ID) SELECT xID, ID FROM inserted
SET @xID = scope_identity()