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

什么是最好的方法来获得插入行的 "IDENTITY"?

我知道@@IDENTITYIDENT_CURRENT以及SCOPE_IDENTITY,但不明白每种方法的优缺点。

谁能解释一下其中的区别,以及我应该在什么时候使用它们?

对该问题的评论 (4)
解决办法
  • @@IDENTITY 返回当前会话中任何表最后生成的身份值,跨越所有作用域。 在这里你需要小心,因为它是跨作用域的。 你可以从触发器中获得一个值,而不是你当前的语句。

  • SCOPE_IDENTITY() 返回当前会话和当前作用域中任何表产生的最后一个身份值。 一般来说,你想使用的是

  • IDENT_CURRENT('tableName') 返回在任何会话和任何范围内为特定表生成的最后身份值。 这让你可以指定你想要哪个表的值,以防上面两个表不是你需要的(**非常罕见)。 另外,正如@Guy Starbuck提到的,"如果你想获得一个你没有插入记录的表的当前IDENTITY值,你可以使用这个。

  • INSERT "语句的 "OUTPUT "子句5可以让你访问通过该语句插入的每一条记录。 由于它是针对特定语句的,所以它比上面的其他函数更直接。 然而,它有点更繁琐**(你需要插入到一个表变量/临时表,然后查询),而且即使在语句被回滚的错误情况下,它也会给出结果。 也就是说,如果你的查询使用了一个并行的执行计划,这是*唯一能保证获得身份的方法(除非关闭并行)。然而,它是在触发器之前执行的,不能用来返回触发器生成的值。

评论(14)

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

例如(取自下面[MSDN][1]的文章)

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

[1]: http://msdn.microsoft.com/en-us/library/ms177564.aspx

评论(7)

我'和其他人说的一样,所以大家'都是对的,我只是想说的更清楚一些。

@@IDENTITY返回你的客户端'连接到数据库的最后插入的东西的id。 大多数情况下,这很好用,但有时触发器会去插入一条你不知道的新行,你'会从这条新行中得到ID,而不是你想要的ID

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

IDENT_CURRENT返回最后被任何人插入的ID。 如果其他应用程序碰巧在一个不恰当的时间插入了另一行,你会得到那行的ID,而不是你的那行。

如果你想安全起见,总是使用SCOPE_IDENTITY()。 如果你坚持使用@@IDENTITY,后来有人决定添加一个触发器,你所有的代码都会被破坏。

评论(0)

获取新插入记录的身份的最好(读作:最安全)方法是使用output子句: 获取新插入记录的标识的最好(读作:最安全)方法是使用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)
评论(4)

添加

SELECT CAST(scope_identity() AS int);

到你的insert sql语句的末尾,然后将

NewId = command.ExecuteScalar()

会检索到它。

评论(0)

当你使用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

输出结果存储在临时表变量中,加入回表,并返回出表的行值。

请注意。 我不知道为什么EF会将表内联接回真实的表(在什么情况下两者会不匹配)。

但这就是EF的工作。

这种技术(OUTPUT)只在SQL Server 2008或更新的版本上可用。

评论(1)

MSDN

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

@@IDENTITY和SCOPE_IDENTITY将返回在当前会话中任何表中产生的最后一个身份值。然而,SCOPE_IDENTITY只返回当前范围内的值;@@IDENTITY则不限于特定范围。

IDENT_CURRENT不受范围和会话的限制;它被限制在一个指定的表中。IDENT_CURRENT返回在任何会话和任何作用域中为一个特定表产生的身份值。更多信息请参见IDENT_CURRENT。

  • IDENT_CURRENT 是一个将表作为参数的函数。
  • @@IDENTITY 当你在表上有一个触发器时,可能返回混乱的结果
  • SCOPE_IDENTITY 在大多数时候是你的英雄。
评论(0)

@@IDENTITY是使用当前SQL连接插入的最后一个身份。 这是一个很好的值,可以从一个插入存储过程中返回,在这里你只需要为你的新记录插入身份,而不关心之后是否有更多的记录被添加。

SCOPE_IDENTITY是使用当前SQL连接并在当前范围内插入的最后一个身份--也就是说,如果在你插入后有第二个基于触发器的IDENTITY插入,它不会反映在SCOPE_IDENTITY中,只会反映在你执行的插入上。坦率地说,我从来没有理由使用这个。

IDENT_CURRENT(tablename)是最后插入的身份,与连接或范围无关。 如果你想获得一个你没有插入记录的表的当前IDENTITY值,你可以使用这个。

评论(2)

我不能说SQL Server的其他版本,但在2012年,直接输出就可以了。 你不'不需要麻烦的临时表。

INSERT INTO MyTable
OUTPUT INSERTED.ID
VALUES (...)

顺便说一下,这种技术在插入多行时也可以使用。

INSERT INTO MyTable
OUTPUT INSERTED.ID
VALUES
    (...),
    (...),
    (...)

产量

ID
2
3
4
评论(2)

总是使用scope_identity(),永远不需要其他东西。

评论(6)

创建一个 "uuid",并将其插入到一列中。 然后你可以很容易地用uuid识别你的行。 这是你唯一可以实现的100%有效的解决方案。 所有其他的解决方案都太复杂了,或者在同样的边缘情况下无法使用。

评论(0)

在你的插入语句后,你需要添加这个。 并确保插入数据的表名,你将得到当前行,而不是刚才插入语句影响的行。

IDENT_CURRENT('tableName')
评论(3)

如果你正在寻找最后添加/更新的ID,这可能有点老派,但有很多人使用旧的PHP,更准确地说,是5.5之前。 更多细节可以在 http://php.net/manual/en/function.mysql-insert-id.php 找到。

$last = mysql_insert_id();
评论(1)