This is a shortened version of my last blog post, but to compensate for the shortness, I've included the code samples directly here (An online runnable demo code is available on rextester.).
SQL Server provides four ways to retrieve the newly generated identity value after rows have been inserted into a table:
All of these ways have their use cases, and there are subtle differences between each of them, that are important to understand.
So what are the differences, and which one should we use?
Ident_Current() are all similar functions because they return values that are inserted into identity columns.
Output is not a function, but a clause we add directly into the DML statement we use.
@@Identity function will return the last identity value inserted in the current session, in any table and in any scope.
Scope_Identity() function will return the last identity value inserted in the current scope (and session), in any table.
Ident_Current() function takes in a table (or view) name and returns the last identity value generated for that table, regardless of session or scope.
output clause returns the values inserted directly from the DML statement it's a part of.
For more details, feel free to read my blog post. For all the details, read the official documentation.
Let's see some code
First, lets create a couple of tables with identity columns:
CREATE TABLE TblIdentityDemo ( id int identity(1,1), col int NOT NULL CONSTRAINT PK_TblIdentityDemo PRIMARY KEY ); CREATE TABLE TblTriggeredWithIdentity ( id int identity(-10,-10), col int CONSTRAINT DF_TblTriggeredWithIdentity_Col DEFAULT(0) );
Then, create an after insert trigger on one table, that will insert records to the other table.
CREATE TRIGGER TblIdentityDemo_Insert ON TblIdentityDemo FOR INSERT AS INSERT INTO TblTriggeredWithIdentity DEFAULT VALUES;
And now - let's play: First, insert a couple of records into the first table:
INSERT INTO TblIdentityDemo (Col) VALUES (1), (2); -- See what happens: SELECT TOP 1 'After a succesful insert' As 'demo', SCOPE_IDENTITY() As [Scope_Identity()], IDENT_CURRENT('TblIdentityDemo') As [IDENT_CURRENT('TblIdentityDemo')], @@IDentity As [@@IDentity], Id, Col FROM TblIdentityDemo ORDER BY Id DESC;
demo Scope_Identity() IDENT_CURRENT('TblIdentityDemo') @@IDentity Id Col After a succesful insert 2 2 -10 2 2
Then, a failed insert (Col is the primary key, so no duplicate values allowed!)
BEGIN TRY INSERT INTO TblIdentityDemo (Col) VALUES (1), (2); END TRY BEGIN CATCH -- Do nothing END CATCH -- Now see what happens: SELECT TOP 1 'After a failed insert' As 'demo', SCOPE_IDENTITY() As [Scope_Identity()], IDENT_CURRENT('TblIdentityDemo') As [IDENT_CURRENT('TblIdentityDemo')], @@IDentity As [@@IDentity], Id, Col FROM TblIdentityDemo ORDER BY Id DESC;
demo Scope_Identity() IDENT_CURRENT('TblIdentityDemo') @@IDentity Id Col After a failed insert 2 3 -10 2 2
And finnaly, a taste of the output clause:
INSERT INTO TblTriggeredWithIdentity (Col) OUTPUT 'output' as 'demo', Inserted.id, Inserted.Col VALUES (1), (2), (3), (4);
demo id Col output -20 1 output -30 2 output -40 3 output -50 4
Top comments (2)
Nice! Although I have to admit I've never seen an identity column type before, what does that do? I've never used SQL Server before, so apologies if that's a super obvious question.
Identity is not a column type but a property you can set on an integer column. (only when creating the column, though).
Once set, SQL Server will automatically populate the identity column with auto-generated values any time you insert rows to the table.
Basically, it's like a
serialcolumn in PostgreSQL or an
auto_incrementcolumn in Oracle / MySql.