Всегда ли вставленные записи получают непрерывные значения идентичности - PullRequest
5 голосов
/ 18 ноября 2010

Рассмотрим следующий SQL:

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

INSERT INTO Foo (Data)
SELECT TOP 1000 Data
FROM SomeOtherTable
WHERE SomeColumn = @SomeParameter

DECLARE @LastID int
SET @LastID = SCOPE_IDENTITY()

Я хотел бы знать, могу ли я зависеть от 1000 строк, которые я вставил в таблицу Foo, имеющих смежные значения идентичности. Другими словами, если этот блок SQL создает @LastID 2000, могу ли я точно знать, что идентификатор первой вставленной мной записи был 1001? Мне в основном любопытно, когда несколько операторов вставляют записи в таблицу Foo одновременно.

Я знаю, что мог бы добавить сериализуемую транзакцию вокруг моего оператора вставки, чтобы обеспечить поведение, которое я хочу, но мне действительно нужно? Я обеспокоен тем, что введение сериализуемой транзакции снизит производительность, но если SQL Server не позволит другим операторам вставлять в таблицу Foo во время выполнения этого оператора, мне не нужно об этом беспокоиться.

Ответы [ 5 ]

7 голосов
/ 19 ноября 2010

Я не согласен с принятым ответом.Это можно легко проверить и опровергнуть, выполнив следующее.

Настройка

USE tempdb

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

Соединение 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

Соединение 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
6 голосов
/ 18 ноября 2010

Да, они будут смежными, потому что ВСТАВКА атомарна: полный успех или полный откат.Это также выполняется как единая единица работы: вы не получите никакого «чередования» с другими процессами

Однако (или чтобы успокоиться!), Рассмотрите предложение OUTPUT

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
3 голосов
/ 18 ноября 2010

Если вы хотите, чтобы значения Identity для нескольких строк использовались OUTPUT:

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

, теперь у вас есть полный набор значений в таблице @NewIDs.Вы можете добавить любые столбцы из таблицы Foo в таблицу @NewIDs, а также вставить эти столбцы.

1 голос
/ 19 ноября 2010

Не стоит придавать какое-либо значение значениям идентичности. Вы должны предположить, что они являются не более чем целыми числами, гарантированно уникальными в пределах вашей таблицы.

0 голосов
/ 10 марта 2011

Попробуйте добавить следующее:

option(maxdop 1)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...