必须用set identity_insert表名on显式开启且每次仅限一张表,插入时须显式列出含自增列的所有列名,完成后必须执行off关闭,否则阻塞后续常规插入。

不能直接插入自增主键值,必须先用 SET IDENTITY_INSERT 显式开启,且每次只允许对一张表生效。
IDENTITY_INSERT 必须按表开启,且同一会话中不能同时开启多张表
SQL Server 不允许“全局”开启自增列手动插入,IDENTITY_INSERT 是以表为单位的会话级设置。开启前需确认目标表当前未被其他会话启用(否则报错 The table 'xxx' already has the IDENTITY_INSERT set to ON)。
- 开启语法严格限定为:
SET IDENTITY_INSERT [schema].[table] ON(方括号可省略,但表名含特殊字符或关键字时必须加) - 关闭必须显式执行:
SET IDENTITY_INSERT [schema].[table] OFF,不能依赖会话结束自动关闭 - 如果在存储过程中开启,务必配对关闭;未关闭就返回结果,后续同表插入会失败
插入语句必须显式列出所有列名,不能用 INSERT INTO table VALUES (...)
一旦启用 IDENTITY_INSERT,SQL Server 强制要求 INSERT 语句中必须包含自增列名 —— 即使你只想插入一行,也得写成 INSERT INTO t (id, name, age) VALUES (100, 'Alice', 25),而不能写 INSERT INTO t VALUES (100, 'Alice', 25)(后者会报错 An explicit value for the identity column in table 't' can only be specified when a column list is used)。
- 列顺序不必与建表顺序一致,但值顺序必须与列名顺序严格对应
- 即使其他列有默认值或允许 NULL,也必须出现在列名列表中(除非你明确不想插入它们)
- 若漏掉非空且无默认值的列,仍会触发常规约束错误,和
IDENTITY_INSERT无关
插入值不能违反自增列的已有约束:重复、越界、类型不匹配
开启 IDENTITY_INSERT 只是绕过“自动生成”限制,并不豁免主键唯一性、数据类型、CHECK 约束等校验。常见翻车点:
- 插入已存在的
id值 → 报错Cannot insert duplicate key row in object 't' with unique index 'PK_t' - 插入负数到
INT IDENTITY(1,1)列 → 允许(只要类型兼容),但后续自动生成可能撞上该值 - 插入超大数值(如
2147483648)到INT列 → 直接溢出报错Arithmetic overflow error converting expression to data type int - 插入字符串到数字型自增列 → 类型转换失败,不是
IDENTITY_INSERT的问题,是基本类型校验
批量插入后记得关掉,否则阻塞后续常规插入
这是最容易被忽略的操作。一旦某张表的 IDENTITY_INSERT 处于 ON 状态,所有未指定主键值的 INSERT INTO t (...) VALUES (...) 都会失败,报错 Explicit value must be specified for identity column...。
- 建议把开启、插入、关闭三步写在同一脚本块里,用
GO分隔(如果是 SSMS 或 sqlcmd) - 不要依赖应用程序连接池复用导致的“意外关闭”,每个开启操作都应有确定的关闭配对
- 可通过查询
SELECT OBJECT_NAME(object_id), name, is_identity FROM sys.columns WHERE is_identity = 1辅助检查哪些表有自增列,但无法查出当前是否开启 —— 没有系统视图暴露该会话状态
真正麻烦的从来不是怎么开,而是开了之后忘了关,或者开了却没列全字段 —— 这两个动作一错,整张表的常规写入就卡住了。










