我应该如何获得插入行的身份?

我知道@@IDENTITY和IDENT_CURRENT和SCOPE_IDENTITY,但不理解它们所附带的含义或影响。

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


当前回答

我不能与其他版本的SQL Server对话,但在2012年,直接输出工作得很好。您不需要为临时表而烦恼。

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

顺便说一下,这种技术也适用于插入多行。

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

输出

ID
2
3
4

其他回答

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

@@IDENTITY返回客户端连接到数据库时插入的最后一个对象的id。 大多数情况下,这工作得很好,但有时触发器会插入一个您不知道的新行,您将从这个新行获得ID,而不是您想要的行

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

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

如果想要安全起见,请始终使用SCOPE_IDENTITY()。如果您坚持使用@@IDENTITY,然后有人决定稍后添加一个触发器,那么您的所有代码都将崩溃。

另一种保证所插入行的身份的方法是指定身份值,并使用SET IDENTITY_INSERT ON和OFF。这保证了您确切地知道标识值是什么!只要这些值没有被使用,就可以将这些值插入到标识列中。

CREATE TABLE #foo 
  ( 
     fooid   INT IDENTITY NOT NULL, 
     fooname VARCHAR(20) 
  ) 

SELECT @@Identity            AS [@@Identity], 
       Scope_identity()      AS [SCOPE_IDENTITY()], 
       Ident_current('#Foo') AS [IDENT_CURRENT] 

SET IDENTITY_INSERT #foo ON 

INSERT INTO #foo 
            (fooid, 
             fooname) 
VALUES      (1, 
             'one'), 
            (2, 
             'Two') 

SET IDENTITY_INSERT #foo OFF 

SELECT @@Identity            AS [@@Identity], 
       Scope_identity()      AS [SCOPE_IDENTITY()], 
       Ident_current('#Foo') AS [IDENT_CURRENT] 

INSERT INTO #foo 
            (fooname) 
VALUES      ('Three') 

SELECT @@Identity            AS [@@Identity], 
       Scope_identity()      AS [SCOPE_IDENTITY()], 
       Ident_current('#Foo') AS [IDENT_CURRENT] 

-- YOU CAN INSERT  
SET IDENTITY_INSERT #foo ON 

INSERT INTO #foo 
            (fooid, 
             fooname) 
VALUES      (10, 
             'Ten'), 
            (11, 
             'Eleven') 

SET IDENTITY_INSERT #foo OFF 

SELECT @@Identity            AS [@@Identity], 
       Scope_identity()      AS [SCOPE_IDENTITY()], 
       Ident_current('#Foo') AS [IDENT_CURRENT] 

SELECT * 
FROM   #foo 

如果您正在从另一个数据源加载数据或合并来自两个数据库的数据等,这可能是一个非常有用的技术。

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

IDENT_CURRENT('tableName')

从MSDN

@@IDENTITY、SCOPE_IDENTITY和IDENT_CURRENT是类似的函数,它们返回插入到表的IDENTITY列中的最后一个值。 @@IDENTITY和SCOPE_IDENTITY将返回当前会话中在任何表中生成的最后一个标识值。然而,SCOPE_IDENTITY只返回当前范围内的值;@@IDENTITY不受特定范围的限制。 IDENT_CURRENT不受作用域和会话的限制;它仅限于指定的表。IDENT_CURRENT返回在任何会话和任何范围内为特定表生成的标识值。有关更多信息,请参见IDENT_CURRENT。

IDENT_CURRENT是一个以表作为参数的函数。 当你在表上有一个触发器时,@@IDENTITY可能返回令人困惑的结果 大多数时候SCOPE_IDENTITY是你的英雄。

Add

SELECT CAST(scope_identity() AS int);

插入SQL语句的末尾

NewId = command.ExecuteScalar()

会取回它。