Peter Larsson Blog

Patron Saint of Lost Yaks

How to get a batch of identity values without OUTPUT

Late this evening I stumbled across a post where OP wanted to get all IDENTITY values for the latest INSERT statement, and correctly OP stated that SCOPE_IDENTITY() only returns last IDENTITY value of the batch.

Well, since OUTPUT is not an option for SQL Server 2000, and if you don't want to include temp tables or other means, this is one way how to solve this issue.
The algorithm relies in implicit transaction; if SPID 60 inserts 5000 records exactly the same time as SPID 61 inserts another 7500 records, the identity values for each spid doesn't get interleaved.

CREATE TABLE    #Sample
                (
                    ID INT IDENTITY(1, 1) PRIMARY KEY CLUSTERED,
                    Dummy INT NOT NULL,
                    Batch INT NOT NULL
                )
 
INSERT  #Sample
SELECT  1, 1
 
SELECT  SCOPE_IDENTITY() - IDENT_INCR('#Sample') * (@@ROWCOUNT - 1) AS FirstID,
        SCOPE_IDENTITY() AS LastID,
        IDENT_INCR('#Sample') AS Increment
 
INSERT  #Sample
SELECT  2, 2 UNION ALL
SELECT  3, 2 UNION ALL
SELECT  4, 2   
 
SELECT  SCOPE_IDENTITY() - IDENT_INCR('#Sample') * (@@ROWCOUNT - 1) AS FirstID,
        SCOPE_IDENTITY() AS LastID,
        IDENT_INCR('#Sample') AS Increment
 
INSERT  #Sample
SELECT  5, 3 UNION ALL
SELECT  6, 3 UNION ALL
SELECT  7, 3 UNION ALL
SELECT  8, 3 UNION ALL
SELECT  9, 3   
 
SELECT  SCOPE_IDENTITY() - IDENT_INCR('#Sample') * (@@ROWCOUNT - 1) AS FirstID,
        SCOPE_IDENTITY() AS LastID,
        IDENT_INCR('#Sample') AS Increment
 
SELECT  *
FROM    #Sample
 
DROP TABLE  #Sample

Legacy Comments


Carl Federl
2009-07-21
re: How to get a batch of identity values without OUTPUT
You may be interested in this confirmed bug where SCOPE_IDENTITY() returns an incorrect value when the insert is from a select query that includes paralellism. https://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=328811

There was also another situation reported where identity values may get interleaved when the inserted target table is partitioned.

Peso
2009-07-21
re: How to get a batch of identity values without OUTPUT
I read the report and it should be fixed in SQL Server 2008. Also I noticed that the SCOPE_IDENTITY() bug exists in SQL Server 2005.
Do you know if the bug exists in SQL Server 2000?

Jeff Moden
2009-07-22
re: How to get a batch of identity values without OUTPUT
>>The algorithm relies in implicit transaction; if SPID 60 inserts 5000 records exactly the same time as SPID 61 inserts another 7500 records, the identity values for each spid doesn't get interleaved.

I'm pretty sure that's not a valid observation, Peter... especially on slower boxes. I'll see if I can find the code that I used to disprove a similar notion before.

--Jeff Moden

Joe Celko
2009-07-23
re: How to get a batch of identity values without OUTPUT
Yet another reason not to use the count of PHYSICAL insertion attempts to the PHYSICAL disk as ay part of a valid LOGICAL model. The guy even confused rows and records!