关于sql:获取插入行标识的最佳方法?

关于sql:获取插入行标识的最佳方法?

Best way to get identity of inserted row?

获取IDENTITY插入行的最佳方法是什么?

我知道@@IDENTITYIDENT_CURRENT以及SCOPE_IDENTITY,但不了解每个附带的利弊。

有人可以解释一下这些差异,以及何时应该使用它们?


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

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

  • IDENT_CURRENT('tableName')返回在任何会话和任何范围内为特定表生成的最后一个标识值。这使您可以指定您想要该值的表,以防上述两个不是您需要的(非常罕见)。此外,正如@Guy Starbuck所提到的,"如果你想获得未插入记录的表的当前IDENTITY值,你可以使用它。"

  • INSERT语句的OUTPUT子句将允许您访问通过该语句插入的每一行。由于它的范围是特定的声明,因此它比上面的其他函数更直接。但是,它更冗长(您需要插入表变量/临时表然后查询)并且即使在回滚语句的错误情况下也会给出结果。也就是说,如果您的查询使用并行执行计划,这是获取身份的唯一保证方法(不能关闭并行性)。但是,它在触发器之前执行,不能用于返回触发器生成的值。


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

例如(摘自以下MSDN文章)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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。如果触发器去创建额外的行,它们将不会导致返回错误的值。万岁

IDENT_CURRENT返回任何人插入的最后一个ID。如果某个其他应用程序恰好在不合适的时间插入另一行,您将获得该行的ID而不是您的ID。

如果您想安全地玩,请始终使用SCOPE_IDENTITY()。如果您坚持使用@@IDENTITY并且有人决定稍后添加触发器,那么您的所有代码都将中断。


获取新插入行的标识的最佳(读取:最安全)方法是使用OUTPUT子句:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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)

1
SELECT CAST(scope_identity() AS INT);

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

1
NewId = command.ExecuteScalar()

将检索它。


使用Entity Framework时,它在内部使用OUTPUT技术返回新插入的ID值

1
2
3
4
5
6
7
8
9
10
11
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或更高版本。


MSDN

@@IDENTITY, SCOPE_IDENTITY, and IDENT_CURRENT are similar functions in that they return the last value inserted into the IDENTITY column of a table.

@@IDENTITY and SCOPE_IDENTITY will return the last identity value generated in any table in the current session. However, SCOPE_IDENTITY returns the value only within the current scope; @@IDENTITY is not limited to a specific scope.

IDENT_CURRENT is not limited by scope and session; it is limited to a specified table. IDENT_CURRENT returns the identity value generated for a specific table in any session and any scope. For more information, see IDENT_CURRENT.

  • IDENT_CURRENT是一个以表为参数的函数。
  • 当您在表格上有触发器时,@@ IDENTITY可能会返回令人困惑的结果
  • SCOPE_IDENTITY大部分时间都是你的英雄。

@@ IDENTITY是使用当前SQL连接插入的最后一个标识。这是从插入存储过程返回的一个很好的值,您只需要为新记录插入标识,并且不关心之后是否添加了更多行。

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

无论连接或范围如何,IDENT_CURRENT(tablename)都是插入的最后一个标识。如果要获取尚未插入记录的表的当前IDENTITY值,可以使用此方法。


我无法与其他版本的SQL Server通信,但在2012年,直接输出工作正常。您不需要打扰临时表。

1
2
3
INSERT INTO MyTable
OUTPUT INSERTED.ID
VALUES (...)

顺便说一下,这种技术在插入多行时也有效。

1
2
3
4
5
6
INSERT INTO MyTable
OUTPUT INSERTED.ID
VALUES
    (...),
    (...),
    (...)

产量

1
2
3
4
ID
2
3
4

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


创建uuid并将其插入列。然后,您可以使用uuid轻松识别您的行。


在插入语句之后,您需要添加它。并确保数据插入的表名。您的插入语句刚才会影响当前行的行。

1
IDENT_CURRENT('tableName')

如果您正在寻找添加/更新的最后一个ID,这可能是一个古老的学校,但有很多人使用较旧的PHP,Pre 5.5更精确。更多细节可以在http://php.net/manual/en/function.mysql-insert-id.php找到

1
$last = mysql_insert_id();


推荐阅读

    linux上获取网管命令?

    linux上获取网管命令?,地址,系统,网络,信息,电脑,服务,网关,状态,名字,中心,l

    linux命令行获取ip?

    linux命令行获取ip?,地址,系统,代码,信息,电脑,服务,状态,密码,命令,网卡,【L

    linux命令获取主机名?

    linux命令获取主机名?,工作,地址,管理,系统,信息,命令,目录,软件,代码,策略,L

    linux各种命令的解释?

    linux各种命令的解释?,地址,工作,系统,信息,命令,目录,时间,管理,控制台,常

    linux插入命令模式?

    linux插入命令模式?,工作,系统,地址,管理,信息,时间,命令,目录,平均,项目,Lin

    linux获取网速命令?

    linux获取网速命令?,网络,工具,软件,地址,设备,5G,名称,工作,通讯,分析,linux

    linux路径命令解释?

    linux路径命令解释?,系统,信息,设备,数据,工具,命令,文件,标准,发行,时间,lin

    linux文本中插入命令?

    linux文本中插入命令?,工作,地址,系统,命令,信息,第一,工具,地方,密码,情况,L

    linux命令获取时分秒?

    linux命令获取时分秒?,时间,系统,体系,标准,命令,工具,管理,国家,大陆,信息,l

    linux命令获取机器码?

    linux命令获取机器码?,地址,设备,工作,信息,命令,管理,系统,工具,目录,网络,l

    linux获取用户名命令?

    linux获取用户名命令?,系统,密码,信息,地址,名称,代码,命令,用户名,用户,用

    linux获取时间戳命令?

    linux获取时间戳命令?,时间,地址,工作,系统,数字,连续,信息,命令,管理,位置,l

    linux获取目录命令行?

    linux获取目录命令行?,工作,系统,地址,信息,数据,命令,标准,名称,环境,位置,l

    linux进程命令解释?

    linux进程命令解释?,系统,状态,基础,进程,信息,时间,命令,实时,软件,名称,Lin

    linux的获取ip命令?

    linux的获取ip命令?,地址,网络,系统,信息,设备,终端,技术,命令,数字,名称,lin

    linux关机命令解释?

    linux关机命令解释?,系统,工作,命令,时间,银河,信息,用户,级别,终端,指令,lin

    linuxvi插入命令?

    linuxvi插入命令?,系统,状态,信息,工作,命令,标准,管理,名称,电脑,正规,linux

    linux只获取ip命令?

    linux只获取ip命令?,地址,网络,系统,信息,设备,数字,终端,命令,电脑,技术指

    linux命令行获取公网?

    linux命令行获取公网?,地址,网络,信息,系统,电脑,命令,终端,状态,名称,通信,

    linux命令输入方法?

    linux命令输入方法?,系统,电脑,密码,管理,地址,命令,网站,工具,首开,位置,lin