当从语句OUTPUT
中插入该行时,如何检索插入行的标识值?UPDATE
既不@@IDENTITY
也不SCOPE_IDENTITY()
似乎设置正确。
考虑这段代码:
DECLARE @UpdateTable table (UpdateTableID int IDENTITY, UpdateTableValue int);
DECLARE @InsertTable table (InsertTableID int IDENTITY, UpdateTableValue1 int, UpdateTableValue2 int);
DECLARE @TestValue int = 5;
INSERT INTO @UpdateTable (UpdateTableValue) VALUES (1),(2),(3);
SELECT [@@IDENTITY] = @@IDENTITY, [SCOPE_IDENTITY()] = SCOPE_IDENTITY();
INSERT INTO @InsertTable (UpdateTableValue1, UpdateTableValue2)
SELECT
UpdateTableValue1, UpdateTableValue2
FROM (
UPDATE @UpdateTable
SET UpdateTableValue = UpdateTableValue + @TestValue
OUTPUT deleted.UpdateTableValue, inserted.UpdateTableValue
WHERE UpdateTableID = 2
) AS UpdateResults (UpdateTableValue1, UpdateTableValue2);
SELECT [@@IDENTITY] = @@IDENTITY, [SCOPE_IDENTITY()] = SCOPE_IDENTITY();
最后插入的行的标识值为 1,但@@IDENTITY
and函数从执行最后一条语句之前SCOPE_IDENTITY()
的原始值返回其原始值。INSERT
@@VERSION
:
Microsoft SQL Azure (RTM) - 12.0.2000.8 2019 年 5 月 2 日 20:11:13 版权所有 (C) 2019 Microsoft Corporation
我相信这是因为
@@IDENTITY
与语句SCOPE_IDENTITY()
结合使用时不起作用。UPDATE
虽然我知道对此的自然反应是“为什么它不返回外部 INSERT 的 ID?” 答案是:因为 Scope。UPDATE
语句和INSERT
语句(使用 的结果)OUTPUT
作为一个语句执行,并且本质上在彼此的同一范围内。当引擎执行查询时,它会意识到这一点,因此无法跟踪外部生成的身份INSERT
。您可以通过运行以下查询来证明这一点,该查询将 theUPDATE
和 the拆分INSERT
为两个单独的语句:这会产生正确的结果:
如果您需要从表格中获取身份,据我所知,您有 3 个选项:
OUTPUT
子句以INSERT
捕获生成的 ID。IDENT_CURRENT()
函数获取当前值。如果您使用的是临时表(不是全局临时表),那么
IDENT_CURRENT()
就可以了,因为您可以保证它只会返回您的会话中生成的值(因为这些对象不能通过其他会话获得)。但是,如果您给出的示例就是这样,那么我将使用选项 2 并使用另一个OUTPUT
子句来捕获生成的标识值:然后输出正确的值: