结论:需跨表复用、手动控步长或要求不跳号时选sequence,仅单表自增且容忍间隙则identity更轻量常用;sequence值事务回滚不回退,无内置回收机制。

SQL Server里SEQUENCE和IDENTITY到底该选哪个?
直接说结论:需要跨表复用、手动控制步长或回滚后不跳号,就用SEQUENCE;仅单表自增且不关心事务回滚后的间隙,IDENTITY更轻量、更常用。很多人一上来就建SEQUENCE,结果发现插入性能略低、还容易漏掉NEXT VALUE FOR语法,反而不如IDENTITY省心。
创建SEQUENCE时必须注意的三个参数
START WITH、INCREMENT BY、MINVALUE/MAXVALUE不是可有可无的配置项,它们直接影响后续能否插入成功:
-
START WITH必须是整数,不能是变量或函数(比如START WITH GETDATE()会报错) -
INCREMENT BY为负数时,MINVALUE必须显式指定,否则默认是1,导致第一次调用NEXT VALUE FOR就抛出Sequence has reached its minimum or maximum value - 没加
CYCLE选项时,一旦达到MAXVALUE,再调用就会报错,而不是自动重置
示例(安全写法):
CREATE SEQUENCE dbo.OrderSeq
START WITH 10000
INCREMENT BY 1
MINVALUE 10000
MAXVALUE 99999999
NO CYCLE;
在INSERT语句里正确引用NEXT VALUE FOR
不能把它当默认值直接写在CREATE TABLE里(不像IDENTITY),必须显式出现在VALUES或SELECT子句中。常见错误包括:
- 在多行
INSERT中误以为一次调用能生成多个值——实际每调用一次只返回一个值,多行需多次调用或用SELECT ... FROM sys.dm_exec_describe_first_result_set类方式预生成 - 把
NEXT VALUE FOR dbo.OrderSeq写成(NEXT VALUE FOR dbo.OrderSeq)加括号——语法允许但没必要,且易与子查询混淆 - 在触发器或
INSTEAD OF触发器中重复调用,导致序列号被消耗却未真正插入
推荐写法(单行):
INSERT INTO Orders (OrderID, CustomerName) VALUES (NEXT VALUE FOR dbo.OrderSeq, 'Alice');
多行建议用SELECT + VALUES构造:
INSERT INTO Orders (OrderID, CustomerName)
SELECT NEXT VALUE FOR dbo.OrderSeq, name
FROM (VALUES ('Alice'), ('Bob'), ('Charlie')) AS t(name);
事务回滚后SEQUENCE值不会回退,这是设计使然
这点和IDENTITY完全一致,但更容易被忽略——因为SEQUENCE是独立对象,看起来“更可控”,结果有人在事务里反复试插又回滚,发现序号一路飙升。这不是bug,是SQL Server保证并发安全的代价。
- 没有内置机制能“回收”已取走但未提交的序列值
- 如果业务强依赖连续编号(比如发票号),得额外加
TRY...CATCH捕获错误后人工补偿,或者改用应用层分配+数据库校验 - 监控序列使用情况可用
sys.sequences视图,重点关注current_value和is_exhausted
查当前值:
SELECT current_value, is_exhausted FROM sys.sequences WHERE name = 'OrderSeq';
真要避免跳号,别指望SEQUENCE本身,得从流程上约束插入动作的原子性和失败重试逻辑。











