SQL Server禁止在DEFAULT约束中直接使用NEXT VALUE FOR序列,因其具有副作用且非标量表达式;替代方案包括INSTEAD OF INSERT触发器或显式在INSERT中调用NEXT VALUE FOR。
直接写 DEFAULT NEXT VALUE FOR seq_name 在 CREATE TABLE 里会报错:「默认值不能是序列对象的 NEXT VALUE FOR 表达式」。这是 SQL Server 的硬性限制,不是语法写错了——它明确禁止把序列值当列默认值用。
常见错误现象:Msg 1759, Level 16, State 1: Default constraint 'DF_xxx' references sequence object 'seq_name', which is not allowed.
原因在于 SQL Server 的 DEFAULT 约束只接受常量、内置函数(如 GETDATE())或标量表达式,而 NEXT VALUE FOR 是语句级执行的、有副作用的操作,无法被约束机制安全求值。
这是最贴近“默认值”语义的可行做法,尤其适合已有表或需要严格控制插入逻辑的场景。
INSTEAD OF INSERT
NEXT VALUE FOR seq_name 赋值;其余列从 INSERTED 中取值NULL,不应覆盖;只有列未出现在 INSERT 列表中时才补序列值示例(假设表 orders 有 order_id 列需自动填充):
CREATE TRIGGER tr_orders_insert_default_seqON ordersINSTEAD OF INSERTASBEGIN INSERT INTO orders (order_id, customer_name, created_at) SELECT ISNULL(i.order_id, NEXT VALUE FOR seq_order_id), i.customer_name, ISNULL(i.created_at, GETDATE()) FROM inserted i;END;
虽然不够“自动”,但这是 SQL Server 官方文档明确推荐的方式,性能好、语义清晰、兼容性稳定。
NEXT VALUE FOR 在单条 INSERT 中每行调用一次)SEQUENCE ... NO CACHE(但会降低性能)典型写法:
INSERT INTO orders (order_id, customer_name) VALUES (NEXT VALUE FOR seq_order_id, 'Alice'), (NEXT VALUE FOR seq_order_id, 'Bob');
如果想让应用层少写重复逻辑,可封装成存储过程,参数只接收业务字段,内部拼接 NEXT VALUE FOR。
SQL Server 2012+ 才支持 SEQUENCE,且它和 IDENTITY 的行为差异常被低估:
SEQUENCE 是独立对象,不绑定表或列,可跨表复用,但也意味着没有自动清理机制——删表不会删序列CACHE 方式定义的序列可能跳号(缓存未刷盘就丢失)NEXT VALUE FOR 在同一个查询中多次出现,每次返回不同值(不像变量赋值),这点在 SELECT ... INTO 或 CTE 中易出错NEXT VALUE FOR
真正要用好序列,得先接受它不是 IDENTITY 的平替,而是面向跨表/跨业务编号需求的设计产物——自动默认值只是表象,背后是更精细的编号生命周期管理。