views:

333

answers:

3

After executing an insert, I either select SCOPE_IDENTITY or @@IDENTITY.

SCOPE_IDENTITY returns null but @@IDENTITY does not.

I don't understand how this is possible.

Can you think of a reason why this happens?

A: 

I found this on MSDN:

The SCOPE_IDENTITY() function will return the null value if the function is invoked before any INSERT statements into an identity column occur in the scope.

You can read here: http://msdn.microsoft.com/en-us/library/ms190315.aspx

Your SQL code would be very helpful.

Dustin Laine
+6  A: 

here is one example of how SCOPE_IDENTITY() will be null but @@IDENTITY will have a value:

insert into a table with no identity, that table has an insert trigger that then inserts into a history table with an identity. SCOPE_IDENTITY() will be null (no identity in the local scope), but @@IDENTITY will report the identity from the trigger.

FYI, there is a known bug with SCOPE_IDENTITY(): https://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=328811

Your best bet with identities is to use OUTPUT INTO, it can capture a set of IDs and is not subject to the SCOPE_IDENTITY() bug:

declare @x table (tableID int identity not null primary key, datavalue varchar(10))
declare @y table (tableID int, datavalue varchar(10))

INSERT INTO @x values ('aaaa')
INSERT INTO @x values ('bbbb')
INSERT INTO @x values ('cccc')
INSERT INTO @x values ('dddd')
INSERT INTO @x values ('eeee')


INSERT INTO @x
    (datavalue)
    OUTPUT INSERTED.tableID, INSERTED.datavalue     --<<<<OUTPUT INTO SYNTAX
    INTO @y                                         --<<<<OUTPUT INTO SYNTAX
SELECT
    'value='+CONVERT(varchar(5),dt.NewValue)
    FROM (SELECT id as NewValue from sysobjects where id<20) dt
    ORDER BY dt.NewValue


select * from @x
select * from @y
KM
While true, I don't think it was necessary to get into this much detail about an obscure bug that only manifests itself when you're inserting several rows and trying to retrieve a single identity. `SCOPE_IDENTITY()` works without issue in 99% of cases. Again, this is all correct but for someone who's still learning the difference between `@@IDENTITY` and `SCOPE_IDENTITY()` it might be a bit overwhelming.
Aaronaught
@Aaronaught, the OP doesn't supply the INSERT code, it could be an INSERT-SELECT that is using parallelism. Why I'd even wager that there is a 1% chance of this! ;-) At least in my answer I present two different ways that @@Identity and SCOPE_IDENTITY() can have different values, and not just the BOL definitions of them.
KM
+2  A: 

KM hit the nail on the head:

  • @@IDENTITY gives you the last IDENTITY value inserted - no matter where in which table it was inserted (think triggers, e.g. into audit tables! Or even a cascade of triggers.....)

  • SCOPE_IDENTITY() gives you the last IDENTITY inserted in the scope of your statement, e.g. on the table(s) that your own, actual statement referenced (not those that might have been touched by a trigger)

marc_s
SCOPE_IDENTITY() fails to return proper results when parallelism is used: https://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=328811
KM
I like this answer best - specific and to the point.
Aaronaught