Do Inserted Records Always Receive Contiguous Identity Values

前端 未结 5 1662
终归单人心
终归单人心 2020-12-06 14:16

Consider the following SQL:

CREATE TABLE Foo
(
    ID int IDENTITY(1,1),
    Data nvarchar(max)
)

INSERT INTO Foo (Data)
SELECT TOP 1000 Data
FROM SomeOther         


        
相关标签:
5条回答
  • 2020-12-06 14:47

    Try adding the following:

    option(maxdop 1)

    0 讨论(0)
  • 2020-12-06 14:52

    It is not good practice to attach any sort of meaning whatsoever to identity values. You should assume that they are nothing more than integers guaranteed to be unique within the scope of your table.

    0 讨论(0)
  • 2020-12-06 14:54

    If you want the Identity values for multiple rows use OUTPUT:

    DECLARE @NewIDs table (PKColumn int)
    INSERT INTO Foo (Data)
        OUTPUT INSERTED.PKColumn
        INTO @NewIDs
    SELECT TOP 1000 Data
    FROM SomeOtherTable
    WHERE SomeColumn = @SomeParameter
    

    you now have the entire set of values in the @NewIDs table. You can add any columns from the Foo table into the @NewIDs table and insert those columns as well.

    0 讨论(0)
  • 2020-12-06 15:08

    I disagree with the accepted answer. This can easily be tested and disproved by running the following.

    Setup

    USE tempdb
    
    CREATE TABLE Foo
    (
        ID int IDENTITY(1,1),
        Data nvarchar(max)
    )
    

    Connection 1

    USE tempdb
    
    SET NOCOUNT ON
    WHILE NOT EXISTS(SELECT * FROM master..sysprocesses WHERE context_info = CAST('stop' AS VARBINARY(128) ))
     BEGIN
     INSERT INTO Foo (Data)
     VALUES ('blah')
     END
    

    Connection 2

    USE tempdb
    
    SET NOCOUNT ON
    SET CONTEXT_INFO 0x
    
    DECLARE @Output TABLE(ID INT)
    
    WHILE 1 = 1
    BEGIN
        /*Clear out table variable from previous loop*/
        DELETE FROM  @Output
    
        /*Insert 1000 records*/
        INSERT INTO Foo (Data)
        OUTPUT inserted.ID INTO @Output
        SELECT TOP 1000 NEWID()
        FROM sys.all_columns
    
        IF EXISTS(SELECT * FROM @Output HAVING MAX(ID) - MIN(ID) <> 999 )
            BEGIN
            /*Set Context Info so other connection inserting 
              a single record in a loop terminates itself*/
            DECLARE @stop VARBINARY(128) 
            SET @stop = CAST('stop' AS VARBINARY(128))
            SET CONTEXT_INFO @stop
    
            /*Return results for inspection*/
            SELECT ID, DENSE_RANK() OVER (ORDER BY Grp) AS ContigSection
            FROM 
              (SELECT ID, ID - ROW_NUMBER() OVER (ORDER BY [ID]) AS Grp
               FROM @Output) O
            ORDER BY ID
    
            RETURN
            END
    END
    
    0 讨论(0)
  • 2020-12-06 15:13

    Yes, they will be contiguous because the INSERT is atomic: complete success or full rollback. It is also performed as a single unit of work: you wont get any "interleaving" with other processes

    However (or to put your mind at rest!), consider the OUTPUT clause

    DECLARE @KeyStore TABLE (ID int NOT NULL)
    
    INSERT INTO Foo (Data)
    OUTPUT INSERTED.ID INTO @KeyStore (ID) --this line
    SELECT TOP 1000 Data
    FROM SomeOtherTable
    WHERE SomeColumn = @SomeParameter
    
    0 讨论(0)
提交回复
热议问题