这里是一个最小的复制示例。
数据库:
CREATE TABLE temp (x int IDENTITY(1, 1), y int);
代码(使用VBA和ADO):
Public Sub repro()
Dim cn As New Connection
Dim rs1 As New Recordset
Dim cmd As New Command
Dim rs2 As New Recordset
cn.Open "Provider=SQLNCLI11;Server=myServer;Database=myDatabase;Trusted_Connection=Yes"
rs1.Open "SELECT 1", cn, adOpenForwardOnly ' [X] '
cmd.ActiveConnection = cn
cmd.CommandText = "INSERT INTO temp (y) VALUES (1) "
cmd.Execute
rs2.Open "SELECT @@IDENTITY", cn, adOpenStatic
Debug.Print rs2(0).value
rs2.Close
rs1.Close ' [X] '
cn.Close
End Sub
预期结果:
这个
Debug.Print
行向调试窗口输出一个整数。
实际结果:
这个
调试。打印
线路输出
Null
到调试窗口。
笔记:
-
一旦我移除标记为
[X]
,代码按预期工作(最后插入的标识值写入调试窗口)。
-
这是一个最小的复制示例
:I
知道
服务器端游标是“邪恶的”。我
知道
在这种特殊情况下
SELECT SCOPE_IDENTITY()
插入批处理是获取新插入ID的正确方法。这只是一个用尽可能少的代码再现问题的最小示例。我在修改遗留代码时偶然发现了这个问题。
-
使用SQL Server Native Client 11.0和“classic”MDAC SQL Server ODBC驱动程序进行测试。使用SQL Server 2005和2012进行测试。没什么区别。
我的问题:
这种行为是出于设计,还是我偶然发现了SQL Server错误?如果是前者,记录在哪里?
编辑:将这两个选项(带和不带[X])与SQL Server Profiler跟踪进行比较,有一个显著的区别:当包含[X]行时,连接显然会被删除并重新打开(
Audit Logout
-
Audit Login
)之间
cmd.Execute
和
rs2.Open
. 我想这就是为什么
@@IDENTITY
不再有效。
这就留下了以下问题:为什么ADO(或SQLNCLI11驱动程序?)在一种情况下关闭并重新打开连接,但在另一种情况下不关闭并重新打开连接?这些记录在哪里?