SCOPE_IDENTITY() 是 SQL Server 中获取刚插入自增 ID 的最安全函数,它严格限定于当前会话和当前作用域,不受触发器干扰,必须紧接 INSERT 执行;而 IDENTITY 不是函数,而是定义自增列的属性。

IDENTITY函数根本不存在,别被名字骗了
SQL里没有叫 IDENTITY 的函数。这个词其实是 SQL Server 里定义自增列的属性(比如 id INT IDENTITY(1,1)),不是用来取值的函数。想拿刚插入的自增ID,得用别的机制——而且不同数据库语法完全不同,硬套 IDENTITY 会直接报错。
SQL Server:用 SCOPE_IDENTITY(),别用 @@IDENTITY
SCOPE_IDENTITY() 是最安全的选择,它只返回当前作用域(比如当前存储过程、批处理)内最后生成的自增ID。而 @@IDENTITY 会被触发器干扰——如果插入后触发器又插了一条带自增的记录,@@IDENTITY 就返回触发器里的ID,不是你想要的。
- 必须在
INSERT语句之后立刻调用,不能隔语句 - 不能在 INSERT 和 SELECT 之间加事务控制语句(如
COMMIT),否则可能跨作用域 - 示例:
INSERT INTO users (name) VALUES ('Alice');<br>SELECT SCOPE_IDENTITY() AS new_id;
MySQL:用 LAST_INSERT_ID(),注意它不依赖表名
LAST_INSERT_ID() 返回当前会话中最后一次 INSERT 生成的自增ID,和表名无关,也不受其他会话影响。但它有个关键点:只要 INSERT 没指定自增列值(哪怕插多行),它就只返回第一行的ID;如果显式插入了自增列值(比如 INSERT INTO t(id) VALUES (100)),它就不更新。
- 不要用
SELECT MAX(id)替代——并发时可能拿到别人的数据 - 批量插入时,
LAST_INSERT_ID()返回的是第一行的ID,不是最大值 - 它本身是会话级函数,不需要额外参数,调用即得
PostgreSQL:用 RETURNING 子句,最直观也最推荐
PostgreSQL 不靠函数,而是把取ID这件事直接集成进 INSERT 语句里,用 RETURNING。它不仅能取自增列,还能返回任意计算字段或表达式,且天然避免竞态问题。
- 写法:
INSERT INTO users (name) VALUES ('Bob') RETURNING id; - 支持多行插入并返回全部ID:
INSERT ... VALUES (...), (...) RETURNING id - 如果表用的是
SERIAL或GENERATED ALWAYS AS IDENTITY,都适用 - 注意:不能在普通函数或视图里直接用
RETURNING,必须是顶层 INSERT
IDENTITY 属性和 PostgreSQL 的 IDENTITY 列定义)但行为毫无关系,混淆就踩坑。


















