2

我开始使用 uniqueidentifiers,但遇到了一个意想不到的问题。

首先,在我通常使用 SCOPE_IDENTITY() 的地方,使用 uniqueidentifier 不再可能,尽管在概念上它仍然涉及作为默认值(newid() 或 newsequentialid() 的结果)自动生成的 id 值) 约束。

我决定在 INSERT 语句中使用 OUTPUT 子句将 UUID 输出到表变量。现在我想起来了,OUTPUT 子句使 SCOPE_IDENTITY 过时,考虑到它是实现相同以及更多功能的更清晰和更强大的方法(例如,为所有插入的行获得对多个自动生成的列的清晰和直接访问)。

但是,使用 OUTPUT 后,我现在想知道这会如何影响通常在插入之后的 @@rowcount 测试。@@rowcount 会反映主语句中插入的行数还是输出子句插入表变量中的行数?

您可能认为它不会产生影响(即计数应该是相同的任何一种方式),但它确实会产生影响,因为文档说即使插入语句失败,OUTPUT 子句也会返回值并填充表.

具有 OUTPUT 子句的 UPDATE、INSERT 或 DELETE 语句将向客户端返回行,即使该语句遇到错误并被回滚。如果在运行语句时发生任何错误,则不应使用结果。

它确实提到 @@rowcount 特别是在使用 OUTPUT 时总是反映最外层的语句,但它提到这是嵌套查询的上下文。由于在我的例子中 OUTPUT 子句是最外层语句的一部分,因此如果插入语句失败,@@rowcount 是否会报告插入到输出表中的行数尚不清楚。

    declare @new_uuid TABLE (ID uniqueidentifier);
    insert into Users (ID, PersonID, Username, Password, Notes, Enabled)
    output INSERTED.UUID into @new_uuid
        values (@id, @personid, @username, @password, @notes, @enabled )
    if (@@rowcount <> 1) goto fail; --does this reflect rows inserted into Users or @new_uuid?  What if the insert fails, and rows are still output to @new_uuid?
4

1 回答 1

3

我已经通过以下 TSQL 代码实验性地测试了这种行为:

create function NEWOBJECTID() returns int as begin return 1 / 0; end --function that would typically perform work to create a new object id, but intentionally throws an error instead
go

declare @uuidtable table (UUID uniqueidentifier);

insert into Users (ID)
output INSERTED.UUID into @uuidtable --UUID column has default constraint of (newid())
values (dbo.NEWOBJECTID()); --value to insert will throw an error

print @@rowcount; --called immediately after statement to see how it was affected by the failure
select * from @idtable; --see if anything was output into the table variable

该语句的结果是@@rowcount 返回零,并且@uuidtable 变量中存在零行,但请继续阅读,因为此结果具有误导性。

首先,这让我相信,由于没有插入任何行,所以不会发生 OUTPUT。这是错误的,一个简单的修改就证明了这一点。

insert into Users (ID)
output INSERTED.UUID into @uuidtable --UUID column has default constraint of (newid())
values
(1), --value to insert should succeed
(2), --value to insert should succeed
(dbo.NEWOBJECTID()); --value to insert will throw an error

当我这次运行它时,@@rowcount 仍然为零;但是,带有两个新唯一标识符的 2 行被输出到 @uuidtable 中。

这表明@@rowcount 反映了最终插入的行数,为零,因为虽然前两个值已成功插入并输出到@uuidtable,但由于错误导致整个语句回滚。

由于在 OUTPUT 表中插入了两行,但由于语句失败,最终插入了零行,而@@rowcount 报告为零,这证明它反映了插入语句本身插入的行数,而不是数量一路插入到 OUTPUT 表中的行数。这也证实了文档所说的,即使整个语句失败,行也将是 OUTPUT。

于 2013-11-07T21:26:09.847 回答