AA.*_*.SC 42 sql-server sql-server-2008-r2 identity
哪个是获取我刚刚通过插入生成的标识值的最佳选择?这些语句对性能有什么影响?
SCOPE_IDENTITY() MAX()TOP 1IdentityColumn FROM TableNameORDER BY IdentityColumn DESCAar*_*and 64
用 SCOPE_IDENTITY()如果您插入单行并希望检索生成的ID。
CREATE TABLE #a(identity_column INT IDENTITY(1,1), x CHAR(1));
INSERT #a(x) VALUES('a');
SELECT SCOPE_IDENTITY();
Run Code Online (Sandbox Code Playgroud)
结果:
----
1
Run Code Online (Sandbox Code Playgroud)
OUTPUT如果您要插入多行并需要检索集合,请使用该子句生成的 ID,。
INSERT #a(x)
OUTPUT inserted.identity_column
VALUES('b'),('c');
Run Code Online (Sandbox Code Playgroud)
结果:
----
2
3
Run Code Online (Sandbox Code Playgroud)
为什么这是最好的更快的选择?
除了性能之外,这些是唯一可以保证在默认隔离级别和/或多个用户下正确的。即使您忽略正确性方面,SQL Server 也会将插入的值保存在SCOPE_IDENTITY()也会将在内存中,因此这自然会比针对表或系统表运行您自己的隔离查询更快。
忽略正确性方面就像告诉邮递员他今天的邮件投递做得很好——他比平均时间快了 10 分钟完成了他的路线,问题是,没有一封邮件被投递到正确的房子。
请勿使用以下任何一种:
@@IDENTITY - 因为这不能在所有场景中使用,例如,当一个带有标识列的表有一个触发器,该触发器也插入到另一个具有自己标识列的表中时 - 你会得到错误的值。IDENT_CURRENT()- 我在这里详细介绍,评论也很有用,但本质上,在并发情况下,您经常会得到错误的答案。MAX()或者TOP 1- 您必须使用可序列化的隔离来保护这两个语句,以确保MAX()您得到的不是别人的。这比仅使用SCOPE_IDENTITY().每当您插入两行或更多行时,这些函数也会失败,并且需要生成所有标识值 - 您唯一的选择是OUTPUT子句。
除了性能之外,它们都有不同的含义。
SCOPE_IDENTITY()将为您提供直接插入当前范围内任何表的最后一个标识值(范围 = 批处理、存储过程等,但不在当前范围内触发的触发器内)。
IDENT_CURRENT()将为您提供任何用户从任何范围插入到特定表中的最后一个标识值。
@@IDENTITY为您提供由当前连接的最新 INSERT 语句生成的最后一个标识值,无论表或范围如何。(旁注:Access 使用此函数,因此在将值插入具有标识列的表中的触发器方面存在一些问题。)
使用MAX()或TOP 1如果表具有否定的标识步骤,或者已插入行,则可能会给您完全错误的结果SET IDENTITY_INSERT。这是一个演示所有这些的脚本:
CREATE TABLE ReverseIdent (
id int IDENTITY(9000,-1) NOT NULL PRIMARY KEY CLUSTERED,
data char(4)
)
INSERT INTO ReverseIdent (data)
VALUES ('a'), ('b'), ('c')
SELECT * FROM ReverseIdent
SELECT IDENT_CURRENT('ReverseIdent') --8998
SELECT MAX(id) FROM ReverseIdent --9000
SET IDENTITY_INSERT ReverseIdent ON
INSERT INTO ReverseIdent (id, data)
VALUES (9005, 'd')
SET IDENTITY_INSERT ReverseIdent OFF
SELECT IDENT_CURRENT('ReverseIdent') --8998
SELECT MAX(id) FROM ReverseIdent --9005
Run Code Online (Sandbox Code Playgroud)
总结:坚持使用SCOPE_IDENTITY(), IDENT_CURRENT(), or @@IDENTITY,并确保您使用的是返回您实际需要的那个。
| 归档时间: |
|
| 查看次数: |
217588 次 |
| 最近记录: |