是否总是按照 SQL Server 中的插入顺序给出自动递增标识?

cto*_*orx 5 sql-server identity

如果我创建一个这样的简单表:

CREATE TABLE SimpleTable (
     [Id] INT IDENTITY(1,1) NOT NULL,
     [Value] VARCHAR(10) NOT NULL,
     CONSTRAINT [PK_Email] PRIMARY KEY CLUSTERED 
     (
         [Id] ASC
     ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
Run Code Online (Sandbox Code Playgroud)

然后我在同一个事务中插入表 100 次,就像这样......

TRUNCATE TABLE SimpleTable -- ensure reset identity seed

BEGIN TRAN

INSERT INTO SimpleTable(Value) VALUES('First')
INSERT INTO SimpleTable(Value) VALUES('Second')
INSERT INTO SimpleTable(Value) VALUES('Third')
INSERT INTO SimpleTable(Value) VALUES('Fourth')
/* ... etc */
INSERT INTO SimpleTable(Value) VALUES('Hundredth')

COMMIT TRAN
Run Code Online (Sandbox Code Playgroud)

是否可以保证插入的行将按照插入语句的执行顺序获得标识值?

更具体地说,如果我在插入后运行此查询...

SELECT * FROM SimpleTable ORDER BY 1
Run Code Online (Sandbox Code Playgroud)

我会经常看到这个吗...

Id    Value
----------------------------------------------
1     First
2     Second
3     Third
4     Fourth
... etc
100   Hundredth
Run Code Online (Sandbox Code Playgroud)

或者,SQL 不保证这一点吗?

Cha*_*tox 10

如果这是该表上唯一的事务,那么是的。但是,除非您使用SERIALIZABLE隔离,否则另一个事务也可以同时执行插入操作,并且介于 1-100 之间。

来自产品文档中的IDENTITY (Property) (Transact-SQL)

列上的标识属性不保证以下内容:

  • 值的唯一性 – 必须通过使用 PRIMARY KEY 或 UNIQUE 约束或 UNIQUE 索引来强制执行唯一性。

  • 事务中的连续值 – 插入多行的事务不能保证获得这些行的连续值,因为其他并发插入可能会发生在表上。如果值必须是连续的,那么事务应该在表上使用排他锁或使用 SERIALIZABLE 隔离级别。

  • 服务器重新启动或其他故障后的连续值 - SQL Server 可能会出于性能原因缓存标识值,并且某些分配的值可能会在数据库故障或服务器重新启动期间丢失。这可能会导致插入时标识值出现间隙。如果间隙不可接受,则应用程序应使用其自己的机制来生成键值。使用带有 NOCACHE 选项的序列生成器可以限制从未提交的事务的间隔。

  • 值的重用——对于具有特定种子/增量的给定身份属性,引擎不会重用身份值。如果特定的插入语句失败或插入语句被回滚,则使用的标识值将丢失并且不会再次生成。这可能会导致生成后续标识值时出现间隙