代码之家  ›  专栏  ›  技术社区  ›  Heinzi

服务器端仅向前游标中断@标识

  •  3
  • Heinzi  · 技术社区  · 6 年前

    这里是一个最小的复制示例。

    数据库:

    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驱动程序?)在一种情况下关闭并重新打开连接,但在另一种情况下不关闭并重新打开连接?这些记录在哪里?

    2 回复  |  直到 6 年前
        1
  •  2
  •   Alex K.    6 年前

    MARS是默认行为的更好替代品,默认行为实际上允许多个记录集。

    发生的情况是:

    1. SELECT 1 充当连接的活动记录集;保持打开状态
    2. 然后执行 insert 提供程序知道它有一个活动的记录集,并试图通过创建一个新的连接来执行语句而不干扰任何内容来提供帮助
    3. 此临时连接执行 插入 然后通过执行注销-销毁与之相关的状态来进行整理
    4. select @@identity 再次使用临时连接,其中 @@identity 因为前面的语句超出了范围,因此 NULL .

    enter image description here

        2
  •  0
  •   sarin    6 年前

    我注意到您正在同一连接上进行两次选择。您是否尝试过通过在连接字符串中添加“MultipleActiveResultSets=True”来启用“多个活动结果集”?

    Enabling Multiple Active Result Sets on MSDN