Scope_Identity(),Identity(),@@ Identity和Ident_Current()有什么区别?

我知道Scope_Identity()Identity()@@IdentityIdent_Current()都可以获得标识列的值,但我很想知道它们之间的区别。

我遇到的争议的一部分是什么意思的范围适用于上述这些function?

我也喜欢使用它们的不同场景的一个简单的例子?

  • @@identity函数返回在同一会话中创build的最后一个标识。
  • scope_identity()函数返回在同一会话中创build的最后一个标识和相同的作用域。
  • ident_current(name)返回在任何会话中为特定表或视图创build的最后一个标识。
  • identity()函数不用于获取标识,它用于在select...into查询中创build标识。

会话是数据库连接。 作用域是当前查询或当前的存储过程。

scope_identity()@@identity函数不同的情况是,如果您在表上有触发器。 如果你有一个插入logging的查询,导致触发器在某处插入另一个logging,那么scope_identity()函数将返回由查询创build的标识,而@@identity函数将返回由触发器创build的标识。

所以,通常你会使用scope_identity()函数。

好问题。

  • @@IDENTITY :返回在您的SQL连接(SPID)上生成的最后一个标识值。 大多数情况下,这将是你想要的,但有时却不是(例如,当触发器响应INSERT而触发,并且触发器执行另一个INSERT语句时)。

  • SCOPE_IDENTITY() :返回当前作用域(即存储过程,触发器,函数等)中生成的最后一个标识值。

  • IDENT_CURRENT() :返回特定表的最后一个标识值。 不要使用它从INSERT获取标识值,它受竞争条件(即在同一个表上插入多行的多个连接)的影响。

  • IDENTITY() :用于在表中声明列作为标识列时使用。

有关更多参考,请参阅: http : //msdn.microsoft.com/en-us/library/ms187342.aspx 。

总结一下:如果要插入行,并且想要知道刚刚插入的行的标识列的值,则始终使用SCOPE_IDENTITY()

如果你理解范围和会话之间的区别,那么理解这些方法将会非常容易。

亚当·安德森的一篇非常好的博客文章描述了这种差异:

会话意味着正在执行命令的当前连接。

范围意味着命令的直接上下文。 每个存储过程调用都在其自己的作用域中执行,嵌套调用在调用过程作用域内的嵌套作用域中执行。 同样,从应用程序或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 

给出不同的结果。

@@Identity澄清问题:

例如,如果插入一个表,并且该表具有触发器进行插入, @@Identity将从触发器( log_id或某事)的插入中返回id,而scope_identity()将返回原始插入器中的id表。

所以如果你没有任何触发器, scope_identity()@@identity将返回相同的值。 如果你有触发器,你需要考虑你想要的价值。

由于@David Freitas提到的错误,以及由于2012年推出的新Sequencefunction的不兼容性,我build议远离这三个。 相反,您可以使用OUTPUT子句来获取插入的标识值。 另一个优点是,如果插入了多行,OUTPUT甚至可以工作。

有关详细信息和示例,请参阅此处: 身份危机

Scope Identity :正在执行的存储过程中添加的最后一条logging的标识。

@@Identity :在查询批处理中添加的最后一条logging的标识,或者作为查询的结果,例如执行插入的过程,然后触发一个触发器,然后插入一条logging将从触发器返回插入logging的标识。

IdentCurrent :分配给表的最后一个标识。

@@ Identity是一个全局variables,用于全局获取最后生成的id。 而scope_identity用于获取作用域(过程或函数)中最后生成的id。 有关更多详细信息,请参阅: – @@ Identity是用于全局获取最后生成的ID的一个Globavariables。 而scope_identity用于获取作用域(过程或函数)中最后生成的id。 欲了解更多详情,请参阅: – http://interview-preparation-for-you.blogspot.com/2011/02/identity-and-scope-identity.html

这是书中另一个很好的解释:

至于SCOPE_IDENTITY和@@ IDENTITY之间的区别,假设你有一个带有三个语句的存储过程P1:
– 生成新的身份值的INSERT
– 对存储过程P2的调用,该存储过程也具有生成新标识值的INSERT语句
– 查询函数SCOPE_IDENTITY和@@ IDENTITY的语句SCOPE_IDENTITY函数将返回由P1(相同的会话和范围)生成的值。 @@ IDENTITY函数将返回由P2生成的值(同一个会话,与范围无关)。