必须先执行 SET IDENTITY_INSERT [table_name] ON,否则显式插入 identity 列值会触发 Msg 544 错误;启用后 INSERT 必须显式列出所有列名(含 identity 列),且同一会话中仅允许一个表启用该设置,插入值会影响后续自增种子并仍受主键、约束等校验。

必须先执行 SET IDENTITY_INSERT [table_name] ON,否则任何显式插入都会失败——这不是权限或语法问题,是 SQL Server 引擎层的硬性拦截。
为什么 INSERT INTO t VALUES (100, 'a') 一定报错?
SQL Server 要求:只要启用了 IDENTITY_INSERT,INSERT 语句就必须显式列出所有列名,包括 identity 列本身。漏掉列名、用 VALUES () 省略列列表、或列顺序与值顺序不匹配,都会触发错误。
- 报错
Msg 545:说明你没在INSERT中写列名列表 - 报错
Msg 8101:说明IDENTITY_INSERT没开,或开了但目标表不对(比如开了users却往orders插) - 即使其他列有默认值或允许
NULL,也得出现在列名列表里——否则 SQL Server 不知道你想跳过哪几列
SET IDENTITY_INSERT 是会话级、单表级的开关
它不是全局设置,也不能跨会话生效;同一会话中,任意时刻最多只能对一张表启用。这是最容易被忽略的并发陷阱。
- 如果另一会话已对
products表启用了ON,你再执行SET IDENTITY_INSERT products ON就会报错:The table 'products' already has the IDENTITY_INSERT set to ON - 启用后未关闭,后续对该表的常规插入(如
INSERT INTO products (name) VALUES ('x'))会直接失败,报错Msg 544 - 在存储过程或事务中启用,必须配对
OFF;异常退出时建议加TRY...CATCH保证关闭
插入值会影响后续自增种子,且不豁免任何约束
开启 IDENTITY_INSERT 只绕过“自动生成”限制,不跳过主键唯一性、数据类型、CHECK 约束等校验。更关键的是,它会重置该列的当前 identity 值。
- 插入
100后,下一次常规插入(没开IDENTITY_INSERT)生成的值是101,而不是原来种子+步长 - 若插入值小于当前种子(比如当前是
50,你插了30),后续自增仍从51开始——但你得自己确保30不重复,否则报Cannot insert duplicate key - 想查当前种子:运行
DBCC CHECKIDENT('table_name');想重置:用DBCC CHECKIDENT('table_name', RESEED, new_value)
最常出问题的地方不在“怎么开”,而在“什么时候关”和“值是否真能被接受”。哪怕脚本跑通了,也要确认插入值没撞上现有主键、没导致未来自增冲突、且 OFF 已执行成功——这三个点缺一不可。

















