Value of SCOPE_IDENTITY() when inserting more than one row

760 Views Asked by At

The documentation for SCOPE_IDENTITY states that it

Returns the last identity value inserted into an identity column in the same scope.

I wonder what last really means. Is it the largest value inserted in current scope, or the value of row that was physically last inserted into the table?

I tried to

  • create table with IDENTITY as a clustered index
    • this worked as expected; return value of SCOPE_IDENTITY was the highest value of identity column inserted
  • create table with IDENTITY as a column with different column as a cluster
    • i tried to use different ORDER BY statements to make sure that the generated IDENTITY didn't match the clustered index in any way
    • SCOPE_IDENTITY always returned the highest value of IDENTITY column reached, even though the identities were generated irrespectively of the clustered index
  • I didn't try a heap table

Why I ask: I stumbled upon a piece of code that inserts multiple rows and that uses SCOPE_IDENTITY to get the highest ID inserted, with which it then performs something. Given how SCOPE_IDENTITY seems to work, it currently works OK, but I wonder if it can bring in unexpected bugs.

My question is:
Should I alway assume that the SCOPE_IDENTITY returns the highest value of IDENTITY inserted (for ascending IDENTITY), no matter how the rows were either physically or logically inserted into the table? Or should I just use OUTPUT and than MAX on the identity column to be sure?

Edit: To put it into code, will following code always result in "This happens everytime", no matter what is in the CREATE TABLE #WithID, SELECT, FROM, WHERE or ORDER BY? Assuming the ID INTEGER IDENTITY(1,1) remains constant.

CREATE TABLE #WithID (ID INTEGER IDENTITY(1,1), SomeData INTEGER);
CREATE TABLE #Outputs (ID INTEGER);

INSERT INTO #WithID
OUTPUT Inserted.ID INTO #Outputs
SELECT Number
FROM dbo.Numbers
WHERE Number < 1000000
ORDER BY Number;

IF SCOPE_IDENTITY() = (SELECT MAX(ID) FROM #Outputs)
  PRINT 'This happens everytime'
ELSE
  PRINT 'Oops...';

note: I don't know how well known it is that the values created by IDENTITY are created in the order of the ORDER BY of the SELECT clause and not in the order the rows are physically inserted into the table.

0

There are 0 best solutions below