一尘不染

将最后一个身份插入表中的最佳方法

sql-server

哪一个是获取我刚刚通过插入生成的标识值的最佳选择?这些陈述对性能有什么影响?

  1. SCOPE_IDENTITY()
  2. 聚合函数MAX()
  3. 从表名中选择TOP 1身份列ORDER BY IdentityColumn DESC

阅读 122

收藏
2022-11-03

共1个答案

一尘不染

如果SCOPE_IDENTITY()您要插入单行并想要检索生成的 ID,请使用此选项。

CREATE TABLE #a(identity_column INT IDENTITY(1,1), x CHAR(1));

INSERT #a(x) VALUES('a');

SELECT SCOPE_IDENTITY();

结果:

----
1

OUTPUT*如果要插入多行并且需要检索生成的 ID*集,请使用该**子句。

INSERT #a(x) 
  OUTPUT inserted.identity_column 
  VALUES('b'),('c');

结果:

----
2
3

为什么这是最好的更快的选择?

撇开性能不谈,这些是唯一保证在默认隔离级别和/或多个用户下正确的。即使您忽略正确性方面,SQL Server 也会将插入的值保存SCOPE_IDENTITY()在内存中,因此这自然会比针对表或系统表运行您自己的独立查询要快。

忽略正确性方面就像告诉邮递员他今天的邮件做得很好 - 他完成了他的路线比他的平均时间快了 10 分钟,问题是,没有一封邮件被送到正确的房子。

不要使用以下任何一种:

  • @@IDENTITY- 因为这不能在所有场景中使用,例如当一个带有标识列的表有一个触发器,该触发器也插入到另一个具有自己的标识列的表中时——你会得到错误的值。
  • IDENT_CURRENT()- 我在这里详细介绍了这一点,评论也是有用的阅读,但本质上,在并发下,你经常会得到错误的答案。
  • MAX()或者TOP 1- 你必须用可序列化的隔离来保护这两个语句,以确保MAX()你得到的不是别人的。这比仅使用SCOPE_IDENTITY().

每当您插入两行或更多行并且需要生成所有标识值时,这些函数也会失败 - 您唯一的选择是OUTPUT子句。

2022-11-03