2017-02-22 134 views
0

我有一个插入语句通过ADODB.Connection.Execute插入到具有标识列的MSSQL服务器上的表中执行,但返回的记录集不会返回新插入的记录的标识。为什么不是SCOPE_IDENTITY()返回我插入的ID?

我试过以下形式获取记录的插入ID。

INSERT INTO blah VALUES (blah); SELECT SCOPE_IDENTITY() 
INSERT INTO blah VALUES (blah); SELECT @@IDENTITY 
INSERT INTO blah OUTPUT INSERTED.ID INTO @ID VALUES(blah); SELECT ID FROM @ID 

在所有情况下,查询记录当回到它不包含身份

var I = DB.Execute(insert_statement_from_above); 
if (I) { 
    var INSERTED_ID = I(0).Value; 
} 

为什么会这样发生?

+1

“自动编号列”,你的意思是标识列? –

+0

感谢您发现术语错误 –

回答

2

检查插入的表是否存在任何INSERT触发器,并检查那些INSERT触发器是否使用SET NOCOUNT ON。

当触发器未指定SET NOCOUNT ON时,如果它更新数据库,它将生成一个结果集,该结果集将出现在包含SCOPE_IDENTITY结果的结果集之前。

请参见:https://msdn.microsoft.com/en-us/library/ms189837.aspx

在现实中正在发生的事情是,记录包含一个或多个结果集。

TRIGGER RESULT SET 
SCOPE_IDENTITY RESULT SET 

当您查询作用域标识的记录集时,实际上是查询触发器输出的结果集。

您可以使用RS.nextRecordset()然后查询SCOPE_IDENTITY,但如果触发可能会或可能不会进行更新你结束了,不知道该结果集包含您的SCOPE_IDENTITY,它是第一或第二,有没有第二个?

触发器指定SET NOCOUNT ON是一种普遍接受的良好做法,但是如果您在触发器中必须具有SET NOCOUNT OFF或者无法控制触发器,则可以使用以下代码解决该问题。

注意:上述示例中的作用域标识将始终是记录集中的最后一个结果集。因此,我们可以按照如下发现:

var I = DB.Execute(insert_statement_from_above); 
if (I) { 
    // find the result set with the scope identity in it 
    while (I.State == 0) { 
    I = I.nextRecordset(); 
    } 
    var INSERTED_ID = I(0).Value; 
} 

这看起来对于无视早前关闭的结果集包含的范围身份的结果集。

另请参见:

State propertynextRecordset()

0

如果这是对你罚款,以防止所有触发器从返回的结果集,服务器选项“不允许从触发器返回结果”可能是你的解决方案。

sp_configure 'disallow results from triggers', 1 
GO 
RECONFIGURE 
GO