@@IDENTITY, SCOPE_IDENTITY(), OUTPUT and other methods of retrieving last identity

SqlSql ServerTsqlIdentityOutput Clause

Sql Problem Overview


I have seen various methods used when retrieving the value of a primary key identity field after insert.

declare @t table (
	id int identity primary key,
	somecol datetime default getdate()
)
insert into @t
default values

select SCOPE_IDENTITY() --returns 1
select @@IDENTITY --returns 1

Returning a table of identities following insert:

Create Table #Testing (  
	id int identity,  
	somedate datetime default getdate()  
)  
insert into #Testing  
output inserted.*  
default values   

What method is proper or better? Is the OUTPUT method scope-safe?

The second code snippet was borrowed from SQL in the Wild

Sql Solutions


Solution 1 - Sql

It depends on what you are trying to do...

@@IDENTITY

Returns the last IDENTITY value produced on a connection, regardless of the table that produced the value, and regardless of the scope of the statement that produced the value. @@IDENTITY will return the last identity value entered into a table in your current session. @@IDENTITY is limited to the current session and is not limited to the current scope. For example, if you have a trigger on a table that causes an identity to be created in another table, you will get the identity that was created last, even if it was the trigger that created it.

SCOPE_IDENTITY()

Returns the last IDENTITY value produced on a connection and by a statement in the same scope, regardless of the table that produced the value. SCOPE_IDENTITY() is similar to @@IDENTITY, but it will also limit the value to your current scope. In other words, it will return the last identity value that you explicitly created, rather than any identity that was created by a trigger or a user defined function.

IDENT_CURRENT()

Returns the last IDENTITY value produced in a table, regardless of the connection and scope of the statement that produced the value. IDENT_CURRENT is limited to a specified table, but not by connection or scope.

Solution 2 - Sql

Note that there is a bug in scope_identity() and @@identity - see MS Connect: https://web.archive.org/web/20130412223343/https://connect.microsoft.com/SQLServer/feedback/details/328811/scope-identity-sometimes-returns-incorrect-value

A quote (from Microsoft):

> I highly recommend using OUTPUT instead of @@IDENTITY in all cases. > It's just the best way there is to read identity and timestamp.

Edited to add: this may be fixed now. Connect is giving me an error, but see:

https://stackoverflow.com/questions/7562917/scope-identity-returning-incorrect-value-fixed

Solution 3 - Sql

There is almost no reason to use anything besides an OUTPUT clause when trying to get the identity of the row(s) just inserted. The OUTPUT clause is scope and table safe.

Here's a simple example of getting the id after inserting a single row...

DECLARE @Inserted AS TABLE (MyTableId INT);

INSERT [MyTable] (MyTableColOne, MyTableColTwo)
OUTPUT Inserted.MyTableId INTO @Inserted
VALUES ('Val1','Val2')

SELECT MyTableId FROM @Inserted

Detailed docs for OUTPUT clause: http://technet.microsoft.com/en-us/library/ms177564.aspx


-- table structure for example:     
CREATE TABLE MyTable (
    MyTableId int NOT NULL IDENTITY (1, 1),
    MyTableColOne varchar(50) NOT NULL,
    MyTableColTwo varchar(50) NOT NULL
)

Solution 4 - Sql

@@Identity is the old school way. Use SCOPE_IDENTITY() in all instances going forward. See MSDN for the repercussions of using @@IDENTITY (they're bad!).

Solution 5 - Sql

SCOPE_IDENTITY is sufficient for single rows and is recommended except in cases where you need to see the result of an intermediate TRIGGER for some reason (why?).

For multiple rows, OUTPUT/OUTPUT INTO is your new best friend and alternative to re-finding the rows and inserting into another table.

Solution 6 - Sql

There is another method available in SQL Server 2005 that is outlined in SQL in the Wild.

This will allow you to retrieve multiple identities after insert. Here's the code from the blog post:

Create Table #Testing (  
	id int identity,  
	somedate datetime default getdate()  
)  
insert into #Testing  
output inserted.*  
default values

Solution 7 - Sql

A small correction to Godeke's answer:

It's not just triggers you need to worry about. Any kind of nested operation, such as stored procs, that causes identifiers to be created could change the value of @@IDENTITY.

Another vote for scope_identity...

Solution 8 - Sql

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSeibarView Question on Stackoverflow
Solution 1 - SqlmsonView Answer on Stackoverflow
Solution 2 - SqlSimon DView Answer on Stackoverflow
Solution 3 - SqlJeremyWeirView Answer on Stackoverflow
Solution 4 - SqljcollumView Answer on Stackoverflow
Solution 5 - SqlCade RouxView Answer on Stackoverflow
Solution 6 - SqlSeibarView Answer on Stackoverflow
Solution 7 - SqlPaul SasikView Answer on Stackoverflow
Solution 8 - SqlPatoView Answer on Stackoverflow