获取插入行身份的最佳方法?

什么是插入行的身份的最佳方式?

我知道@@IDENTITYIDENT_CURRENTSCOPE_IDENTITY但不明白每个附带的优点和缺点。

有人可以解释一下这些差异,什么时候我应该使用它们?

  • @@IDENTITY返回当前会话中任何表中为所有作用域生成的最后一个标识值。 你需要小心 ,因为它跨越了范围。 您可以从触发器中获取值,而不是当前的语句。

  • SCOPE_IDENTITY()返回为当前会话中的任何表和当前范围生成的最后一个标识值。 一般来说你想用什么

  • IDENT_CURRENT('tableName')返回为任何会话和任何作用域中的特定表生成的最后一个标识值。 这可以让你指定你想从哪个表中获得值,以防上面的两个不是你所需要的( 非常less见 )。 另外,正如@ Guy Starbuck所说:“如果你想为没有插入logging的表获取当前的IDENTITY值,你可以使用它。

  • INSERT语句的OUTPUT子句将允许您访问通过该语句插入的每一行。 由于它是作为特定语句的范围,所以比上述其他函数更直接 。 然而,它有点冗长 (你需要插入到一个表variables/临时表中,然后查询),即使在语句被回滚的错误情况下,它也会给出结果。 也就是说,如果您的查询使用并行执行计划,这是获取身份唯一保证的方法 (closures并行性的缺点)。 但是,它触发器之前执行不能用于返回触发器生成的值。

我相信检索插入的id最安全和最准确的方法将使用输出子句。

例如(取自以下MSDN文章)

 USE AdventureWorks2008R2; GO DECLARE @MyTableVar table( NewScrapReasonID smallint, Name varchar(50), ModifiedDate datetime); INSERT Production.ScrapReason OUTPUT INSERTED.ScrapReasonID, INSERTED.Name, INSERTED.ModifiedDate INTO @MyTableVar VALUES (N'Operator error', GETDATE()); --Display the result set of the table variable. SELECT NewScrapReasonID, Name, ModifiedDate FROM @MyTableVar; --Display the result set of the table. SELECT ScrapReasonID, Name, ModifiedDate FROM Production.ScrapReason; GO 

我和其他人说的一样,所以每个人都是对的,我只是想说清楚。

@@IDENTITY返回客户端连接到数据库的最后一个事件的ID。
大多数时候这工作正常,但有时触发器会插入一个你不知道的新行,你会得到这个新行的ID,而不是你想要的

SCOPE_IDENTITY()解决了这个问题。 它返回发送到数据库的SQL代码中插入的最后一个东西的ID。 如果触发器去创build额外的行,它们不会导致返回错误的值。 万岁

IDENT_CURRENT返回任何人插入的最后一个ID。 如果其他应用恰好在不幸的时间插入另一行,则会得到该行的ID而不是您的ID。

如果你想安全玩,总是使用SCOPE_IDENTITY() 。 如果你坚持使用@@IDENTITY并且稍后有人决定添加一个触发器,那么你所有的代码都会中断。

获取新插入行的身份的最佳(读取:最安全)方法是使用output子句:

 create table TableWithIdentity ( IdentityColumnName int identity(1, 1) not null primary key, ... ) -- type of this table's column must match the type of the -- identity column of the table you'll be inserting into declare @IdentityOutput table ( ID int ) insert TableWithIdentity ( ... ) output inserted.IdentityColumnName into @IdentityOutput values ( ... ) select @IdentityValue = (select ID from @IdentityOutput) 

 SELECT CAST(scope_identity() AS int); 

然后到你的插入sql语句的末尾

 NewId = command.ExecuteScalar() 

将检索它。

MSDN

@@ IDENTITY,SCOPE_IDENTITY和IDENT_CURRENT是相似的函数,它们返回插入到表的IDENTITY列中的最后一个值。

@@ IDENTITY和SCOPE_IDENTITY将返回当前会话中任何表中生成的最后一个标识值。 但是,SCOPE_IDENTITY仅在当前范围内返回值; @@ IDENTITY不限于特定的范围。

IDENT_CURRENT不受范围和会话的限制; 它仅限于指定的表格。 IDENT_CURRENT返回为任何会话和任何作用域中的特定表生成的标识值。 有关更多信息,请参阅IDENT_CURRENT。

  • IDENT_CURRENT是一个以表格作为参数的函数。
  • 在桌面上有触发器时, @@ IDENTITY可能会返回混淆结果
  • SCOPE_IDENTITY大部分时间都是你的英雄。

@@ IDENTITY是使用当前SQL连接插入的最后一个标识。 从插入存储过程返回这是一个很好的价值,在这里你只需要为新logging插入标识,而不必关心后面是否添加了更多的行。

SCOPE_IDENTITY是使用当前SQL连接插入的最后一个标识,在当前作用域中 – 也就是说,如果在插入之后基于触发器插入了第二个IDENTITY,则不会反映在SCOPE_IDENTITY中,只有您执行的插入。 坦率地说,我从来没有理由使用这个。

IDENT_CURRENT(表名)是插入的最后一个标识,无论连接或范围如何。 如果你想为没有插入logging的表获取当前的IDENTITY值,你可以使用它。

总是使用scope_identity(),从来没有任何其他的需要。

当您使用entity framework时,它在内部使用OUTPUT技术来返回新插入的ID值

 DECLARE @generated_keys table([Id] uniqueidentifier) INSERT INTO TurboEncabulators(StatorSlots) OUTPUT inserted.TurboEncabulatorID INTO @generated_keys VALUES('Malleable logarithmic casing'); SELECT t.[TurboEncabulatorID ] FROM @generated_keys AS g JOIN dbo.TurboEncabulators AS t ON g.Id = t.TurboEncabulatorID WHERE @@ROWCOUNT > 0 

输出结果存储在一个临时表variables中,并返回到表中,并将行值从表中返回。

注:我不知道为什么EF内部将短暂的表加回到真正的表(在什么情况下两个不匹配)。

但这就是EF所做的。

此技术( OUTPUT )仅适用于SQL Server 2008或更新版本。