我知道Scope_Identity()
,Identity()
,@@Identity
,和Ident_Current()
都得到标识列的值,但我很想知道其中的差别。
我遇到的部分争议是它们在适用于以上这些功能时的范围是什么意思?
我还喜欢使用它们的不同场景的简单示例吗?
我知道Scope_Identity()
,Identity()
,@@Identity
,和Ident_Current()
都得到标识列的值,但我很想知道其中的差别。
我遇到的部分争议是它们在适用于以上这些功能时的范围是什么意思?
我还喜欢使用它们的不同场景的简单示例吗?
Answers:
@@identity
函数返回在同一会话中创建的最后一个标识。scope_identity()
函数返回在同一会话和相同范围内创建的最后一个标识。ident_current(name)
返回的任何会议的特定表或视图中创建的最后一个标识。identity()
函数不用于获取身份,而是用于在select...into
查询中创建身份。会话是数据库连接。范围是当前查询或当前存储过程。
一种情形的scope_identity()
与@@identity
功能的不同,就是如果你有在桌子上的触发器。如果您有插入记录的查询,导致触发器在某处插入另一个记录,则该scope_identity()
函数将返回查询创建的标识,而@@identity
函数将返回由触发器创建的标识。
因此,通常您会使用该scope_identity()
功能。
好问题。
@@IDENTITY
:返回在您的SQL连接(SPID)上生成的最后一个标识值。在大多数情况下,它会是您想要的,但有时不是您想要的(例如,当触发触发器以响应INSERT
,并且触发器执行另一条INSERT
语句时)。
SCOPE_IDENTITY()
:返回当前范围内生成的最后一个标识值(即存储过程,触发器,函数等)。
IDENT_CURRENT()
:返回特定表的最后一个标识值。请勿使用此方法从中获取身份值INSERT
,这取决于竞争条件(即,多个连接在同一张表上插入行)。
IDENTITY()
:在将表中的列声明为标识列时使用。
有关更多参考,请参见:http : //msdn.microsoft.com/zh-cn/library/ms187342.aspx。
总结:如果您要插入行,你想知道该行的标识列的值,您刚插入,一直使用SCOPE_IDENTITY()
。
如果您了解范围和会话之间的区别,那么将很容易理解这些方法。
Adam Anderson在一篇非常不错的博客文章中描述了这种区别:
会话表示正在执行命令的当前连接。
范围是指命令的直接上下文。每个存储过程调用都在其自己的范围内执行,而嵌套调用则在调用过程的范围内的嵌套范围内执行。同样,从应用程序或SSMS执行的SQL命令在其自己的范围内执行,如果该命令触发任何触发器,则每个触发器在其自己的嵌套范围内执行。
因此,三种身份检索方法之间的差异如下:
@@identity
返回在此会话中生成的最后一个标识值,但不包括任何范围。
scope_identity()
返回在此会话和此范围中生成的最后一个标识值。
ident_current()
返回在任何会话和任何作用域中为特定表生成的最后一个标识值。
范围表示执行INSERT
语句的代码上下文,SCOPE_IDENTITY()
与的全局范围相反@@IDENTITY
。
CREATE TABLE Foo(
ID INT IDENTITY(1,1),
Dummy VARCHAR(100)
)
CREATE TABLE FooLog(
ID INT IDENTITY(2,2),
LogText VARCHAR(100)
)
go
CREATE TRIGGER InsertFoo ON Foo AFTER INSERT AS
BEGIN
INSERT INTO FooLog (LogText) VALUES ('inserted Foo')
INSERT INTO FooLog (LogText) SELECT Dummy FROM inserted
END
INSERT INTO Foo (Dummy) VALUES ('x')
SELECT SCOPE_IDENTITY(), @@IDENTITY
给出不同的结果。
由于@David Freitas提到的错误以及与2012年引入的新Sequence功能不兼容,我建议您不要使用这三个功能。相反,您可以使用OUTPUT子句来获取插入的标识值。另一个优点是,即使您插入了多行,OUTPUT仍然有效。
有关详细信息和示例,请参见此处:身份危机
这是本书中的另一个很好的解释:
至于SCOPE_IDENTITY和@@ IDENTITY之间的区别,假设您有一个包含三个语句的存储过程P1:
-生成新标识值
的INSERT-对存储过程P2的调用,该存储过程P2也具有一个生成新ID的INSERT语句身份值
-查询函数SCOPE_IDENTITY和@@ IDENTITY的语句SCOPE_IDENTITY函数将返回由P1生成的值(相同的会话和范围)。@@ IDENTITY函数将返回由P2生成的值(相同的会话,而不管作用域如何)。