Apart from performance, they all have rather different meanings.
SCOPE_IDENTITY() will give you the last identity value inserted into any table directly within the current scope (scope = batch, stored procedure, etc. but not within, say, a trigger that was fired by the current scope).
IDENT_CURRENT() will give you the last identity value inserted into a specific table from any scope, by any user.
@@IDENTITY gives you the last identity value generated by the most recent INSERT statement for the current connection, regardless of table or scope. (Side note: Access uses this function, and thus has some issues with triggers that insert values into tables with identity columns.)
Using MAX() or TOP 1 can give you entirely wrong results if the table has a negative identity step, or has had rows inserted with SET IDENTITY_INSERT in play. Here's a script demonstrating all of these:
CREATE TABLE ReverseIdent (
id int IDENTITY(9000,-1) NOT NULL PRIMARY KEY CLUSTERED,
data char(4)
)
INSERT INTO ReverseIdent (data)
VALUES ('a'), ('b'), ('c')
SELECT * FROM ReverseIdent
SELECT IDENT_CURRENT('ReverseIdent') --8998
SELECT MAX(id) FROM ReverseIdent --9000
SET IDENTITY_INSERT ReverseIdent ON
INSERT INTO ReverseIdent (id, data)
VALUES (9005, 'd')
SET IDENTITY_INSERT ReverseIdent OFF
SELECT IDENT_CURRENT('ReverseIdent') --8998
SELECT MAX(id) FROM ReverseIdent --9005
Summary: stick with SCOPE_IDENTITY(), IDENT_CURRENT(), or @@IDENTITY, and make sure you're using the one that returns what you actually need.
IDENT_CURRENT()and@@IDENTITYwhen your own script demonstrates that they output incorrect results? – Aaron Bertrand Dec 30 '15 at 14:51IDENT_CURRENT()returns. MAX() never returns the right value beyond the first row, since id is counting backwards, and withIDENTITY_INSERTon, 9005 is not a generated identity value, thus not reflected byIDENT_CURRENT(). But it may return "incorrect" results if you're really after whatSCOPE_IDENTITY()returns. Choose the right tool for the job. – db2 Dec 30 '15 at 16:37@@IDENTITYis almost never the ideal way to get generated identity values. The main point is thatMAX()orTOP 1are like a less reliable version ofIDENT_CURRENT(), which is a perfectly fine function to use if you understand what it does. Could be useful for maintenance jobs or something. – db2 Dec 30 '15 at 17:54