Here is a minimal repro example.
Database:
CREATE TABLE temp (x int IDENTITY(1, 1), y int);
Code (using VBA and 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
Expected result: The Debug.Print
line outputs an integer to the debug window.
Actual result: The Debug.Print
line outputs Null
to the debug window.
Notes:
- As soon as I remove the lines marked as
[X]
, the code works as expected (the last inserted identity value is written to the debug window). - This is a minimal repro example: I know that server-side cursors are "evil". I know that in this particular case adding
SELECT SCOPE_IDENTITY()
to the INSERT batch is the correct way to get the newly inserted ID. This is just a minimal example to reproduce the issue with the least code possible. I stumbled upon this issue while modifying legacy code. - Tested with both SQL Server Native Client 11.0 and the "classic" MDAC SQL Server ODBC driver. Tested with SQL Server 2005 and 2012. Doesn't make a difference.
My question: Is this behavior by design, or did I stumble upon an SQL Server bug? If the former, where is it documented?
EDIT: Comparing the two options (with and without [X]) with an SQL Server Profiler trace, there is one significant difference: When the [X] lines are included, the connection is apparently dropped and reopened (Audit Logout
- Audit Login
) between cmd.Execute
and rs2.Open
. I guess that explains why @@IDENTITY
no longer works.
That leaves the following question: Why does ADO (or the SQLNCLI11 driver?) close and reopen the connection in one case but not in the other case? And where is this documented?