考虑以下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()
我想知道我是否可以依赖于我插入表Foo中的具有连续标识值的1000行。换句话说,如果这个SQL块产生的@LastID为2000,我能否确定我插入的第一条记录的ID是1001?我主要是对多个语句同时将记录插入表Foo感到好奇。
我知道我可以在insert语句周围添加一个可序列化的事务来确保我想要的行为,但我真的需要吗?我担心引入可序列化的事务会降低性能,但如果SQL Server在此语句运行时不允许其他语句插入到表Foo中,那么我不必担心它。
答案 0 :(得分:7)
我不同意接受的答案。通过运行以下内容,可以轻松测试和反驳这一点。
<强>设置强>
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
答案 1 :(得分:6)
是的,它们将是连续的,因为INSERT是原子的:完全成功或完全回滚。它也作为一个单独的工作单元执行:你不会与其他进程“交错”
然而(或者让你放松心情!),请考虑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
答案 2 :(得分:3)
如果您想要多行的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表中,也可以插入这些列。
答案 3 :(得分:1)
将任何形式的意义附加到身份价值上并不是一种好的做法。你应该假设它们只不过是在表范围内保证唯一的整数。
答案 4 :(得分:0)
尝试添加以下内容:
option(maxdop 1)