使用表变量的 SQL Server 2005 存储过程不会将结果集返回到 VB6 应用程序

发布于 2024-09-07 13:41:48 字数 3322 浏览 1 评论 0原文

我有一个存储过程,它从一行中选择一个字段(基于条件语句)并将其存储在局部变量中。根据该字段的值,我更新表同一行中的同一字段(使用相同的条件语句)。因此,该过程首先对局部变量进行选择,然后更新同一行的同一字段。然后,该过程通过对表变量的选择返回结果集(我也尝试使用临时表)。结果集不包含我更新的变量或字段。它甚至不包括该表中的任何字段。

当从 Management Studio 或测试 C# 应用程序调用时,该过程可以正常工作。但是,当从我的 VB6 应用程序调用时,不会返回结果集。然而,所有数据库更新仍然执行。

我尝试过使用事务和不使用事务、使用 TRY...CATCH 和不使用事务以及同时编写存储过程。我尝试过事务隔离的各种组合。不会抛出任何异常,并且事务将始终提交。我还在 select 语句上使用了WITH (NOLOCK) 提示。如果我省略表更新它就会起作用。如果我省略对局部变量的赋值,而是硬编码一个值,它就可以工作。如果我只是在放置变量的地方使用 select ,它将无法工作。

有趣的是,如果我向过程中添加一些随机选择语句,它将返回该结果集。我什至可以从分配给变量的同一记录中选择同一字段,没有任何问题。但它仍然不会返回我想要的结果集。

我的结果集是从表变量中选择的,该变量是通过使用整个过程中设置的变量通过插入语句填充的。根本没有表连接。我确实向该过程传递了 2 个参数 - 其中一个参数在原始选择的条件语句中使用。但当我省略参数和硬代码值时,我仍然会得到相同的行为。

我尝试过重新启动我的SQL Server(2005版本9.0.4053),重新启动我的机器,我尝试过NOCOUNT ON和OFF,我基本上没有想法。

编辑 - VB 调用和存储过程签名的详细信息:
我将尝试在不发布实际代码的情况下提供尽可能详细的描述。实际上,我是为与我一起工作的另一位开发人员发布此内容的,所以请耐心等待。

VB6 调用:

 With cmdCommand
        .ActiveConnection = cnnConn
        .CommandType = adCmdStoredProc
        .CommandText = "uspMyStoredProcedure"
        .Parameters("@strParam1") = strFunctionParameter1
        .Parameters("@bolParam2") = bolFunctionParameter2
        .Execute
 End With

MyResultSet.CursorLocation = adUseClient
MyResultSet.Open cmdCommand, , adOpenStatic, adLockReadOnly

存储过程签名:

CREATE PROCEDURE uspMyStoredProcedure
    @strParam1 NVARCHAR(XX),
    @bolParam2 BIT

AS
BEGIN
    SET NO COUNT ON

    DECLARE @var1 NVARCHAR(XX),
    @var2 NVARCHAR(XX),
    @var3 NVARCHAR(XX),
    @var4 INT,
    @var5 BIT
    --DECLARATION OF OTHER VARIABLES


    DECLARE  @varTableVariable TABLE
    (
      strTblVar1 NVARCHAR(XX) ,
      intTblVar2 INT ,
      strTblVar3 NVARCHAR(XX) ,
      bolTblVar4 BIT ,
      datTblVar5 DATETIME
    )

    SELECT @var1 = t.Field1, @var2 = t.Field2
    FROM Table1 t
    WHERE t.ID = @strParam1

    SELECT @var3 = t2.Field1
    FROM Table2 t2

    IF (Condition)
    BEGIN
        SET @var4 = 1
        IF (Condition)
        BEGIN
            --SET SOME VARIABLES
        END
        ELSE
        BEGIN
            UPDATE TABLE1
            SET Field3 = @var4
            WHERE Field1 = @strParam1
        END
    END
    ELSE
    BEGIN
        IF(Condition)
        BEGIN
            SELECT @var5 = ISNULL(Condition)
            FROM Table3 t3
            WHERE t3.Field = @strParam1

            --SET SOME MORE VARIABLES
        END
    END

    IF(Condition)
    BEGIN
        UPDATE Table1
        SET Field5 = @SomeVariable
        WHERE Field1 = @strParam1
    END

    INSERT INTO Table4 (Field1, Field2, Field3)
    SELECT @SomeVar1, @someVar2, @SomeVar3
    FROM SomeOtherTable
    WHERE Field3 = @someVariable

    IF(Condition)
    BEGIN
        INSERT INTO @varTableVariable (strTblVar1, intTblVar2, 
        strTblVar3, bolTblVar4,  datTblVar5 )
        VALUES (@SomeVar1, @SomeVar2, @SomeVar3, @SomeVar4, @SomeVar5)
    END

SELECT *
FROM @varTableVariable

END

因此,本质上,该过程采用两个参数。它执行许多简单的操作 - 从几个不同的表中插入和选择数据、更新表以及将行插入表变量。

该过程以从表变量中进行选择结束。该过程或来自 VB6 的调用没有什么特别之处。如前所述,观察到的行为是不寻常的,因为通过注释掉某些部分,调用和返回将起作用 - 返回数据。从 C#.NET 测试应用程序调用相同的过程可以正常工作并成功返回所需的结果。

我们设法返回 VB6 应用程序的只是一个空记录集。

编辑2:我们刚刚发现,如果我们创建一个任意表来保存最终 select 语句返回的数据而不是使用表变量,则该过程将有效...

I have a stored procedure which selects a single field from a single row (based on a conditional statement) and stores it in a local variable. Based on the value of this field I update the same field in the same row of the table (using the same conditional statement). So the procedure first does a select into a local variable and then later updates the same field of the same row. The procedure then returns a result set via a select on a table variable (I have also attempted using a temporary table). The result set does not contain the variable or field I have updated. It doesn't even include any fields from this table.

The procedure works correctly when called from either Management Studio or from a test C# application. However, when called from my VB6 app the result set is not returned. All database updates are still performed however.

I have tried writing the stored procedure with a transaction and without, with TRY...CATCH and without, and both at the same time. I've tried various combinations of transaction isolation. No exceptions are thrown and the transaction will always commit. I've also used the WITH (NOLOCK) hint on the select statement. If I leave out the table update it will work. If I leave out the assignment to a local variable and instead hard code a value it works. If I simply use the select where I would put the variable it will NOT work.

Interestingly, if I add some random select statement to the procedure it will return that result set. I can even select that same field from the same record I assign to my variable with no issue. But it still will not return my desired result set.

My result set is a select from a table variable which is populated via insert statements using variables set throughout the procedure. There are no table joins at all. I do pass 2 parameters to the procedure - one of which is used in my conditional statement in the original select. But I still get the same behavior when I omit both parameters and hard code values.

I have tried restarting my SQL Server (2005 version 9.0.4053), restarting my machine, i have tried with NOCOUNT ON and OFF, I'm basically out of ideas.

Edit - Details of VB call and stored procedure signature:
I'll try to give as good as a description as I can without publishing actual code. I'm actually posting this for another developer who works with me, so please bear with me.

VB6 Call:

 With cmdCommand
        .ActiveConnection = cnnConn
        .CommandType = adCmdStoredProc
        .CommandText = "uspMyStoredProcedure"
        .Parameters("@strParam1") = strFunctionParameter1
        .Parameters("@bolParam2") = bolFunctionParameter2
        .Execute
 End With

MyResultSet.CursorLocation = adUseClient
MyResultSet.Open cmdCommand, , adOpenStatic, adLockReadOnly

Stored Procedure signature:

CREATE PROCEDURE uspMyStoredProcedure
    @strParam1 NVARCHAR(XX),
    @bolParam2 BIT

AS
BEGIN
    SET NO COUNT ON

    DECLARE @var1 NVARCHAR(XX),
    @var2 NVARCHAR(XX),
    @var3 NVARCHAR(XX),
    @var4 INT,
    @var5 BIT
    --DECLARATION OF OTHER VARIABLES


    DECLARE  @varTableVariable TABLE
    (
      strTblVar1 NVARCHAR(XX) ,
      intTblVar2 INT ,
      strTblVar3 NVARCHAR(XX) ,
      bolTblVar4 BIT ,
      datTblVar5 DATETIME
    )

    SELECT @var1 = t.Field1, @var2 = t.Field2
    FROM Table1 t
    WHERE t.ID = @strParam1

    SELECT @var3 = t2.Field1
    FROM Table2 t2

    IF (Condition)
    BEGIN
        SET @var4 = 1
        IF (Condition)
        BEGIN
            --SET SOME VARIABLES
        END
        ELSE
        BEGIN
            UPDATE TABLE1
            SET Field3 = @var4
            WHERE Field1 = @strParam1
        END
    END
    ELSE
    BEGIN
        IF(Condition)
        BEGIN
            SELECT @var5 = ISNULL(Condition)
            FROM Table3 t3
            WHERE t3.Field = @strParam1

            --SET SOME MORE VARIABLES
        END
    END

    IF(Condition)
    BEGIN
        UPDATE Table1
        SET Field5 = @SomeVariable
        WHERE Field1 = @strParam1
    END

    INSERT INTO Table4 (Field1, Field2, Field3)
    SELECT @SomeVar1, @someVar2, @SomeVar3
    FROM SomeOtherTable
    WHERE Field3 = @someVariable

    IF(Condition)
    BEGIN
        INSERT INTO @varTableVariable (strTblVar1, intTblVar2, 
        strTblVar3, bolTblVar4,  datTblVar5 )
        VALUES (@SomeVar1, @SomeVar2, @SomeVar3, @SomeVar4, @SomeVar5)
    END

SELECT *
FROM @varTableVariable

END

So, essentially, the procedure takes two parameters. It carries out a number of simple operations - inserting and selecting data from a couple of different tables, an update to a table and inserting a row into a table variable.

The procedure finishes with a select from the table variable. There's nothing fancy about the procedure, or the call from VB6. As previously stated, the behaviour observed is unusual in that by commenting out certain sections the call and return will work - data is returned. Calling the same procedure from a C#.NET test app works and successfully returns the desired result.

All we manage to get back in the VB6 app is an empty recordset.

Edit 2: We've just found out that if we create an arbitrary table to hold the data to be returned by the final select statement instead of using a table variable, the procedure works...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

请帮我爱他 2024-09-14 13:41:48

我们发现,由于从 VB6 调用存储过程的方式,该存储过程实际上执行了两次:

With cmdCommand
        .ActiveConnection = cnnConn
        .CommandType = adCmdStoredProc
        .CommandText = "uspMyStoredProcedure"
        .Parameters("@strParam1") = strFunctionParameter1
        .Parameters("@bolParam2") = bolFunctionParameter2
        .Execute 
 End With

MyResultSet.CursorLocation = adUseClient
MyResultSet.Open cmdCommand, , adOpenStatic, adLockReadOnly 

命令对象“cmdCommand”第一次执行时,显式调用作为“With”语句中的最后一行,“.执行'。

我们发现最后一行:“MyResultSet.Open cmdCommand...”也隐式第二次执行存储过程。

由于存储过程的功能本质上是激活和停用警报,因此通过执行两次,我们会同时发生激活和停用,因此不会返回结果集。

希望这可以帮助避免其他人陷入这样的困境。

We discovered that the stored procedure was actually executing twice, due to the way it was being called from VB6:

With cmdCommand
        .ActiveConnection = cnnConn
        .CommandType = adCmdStoredProc
        .CommandText = "uspMyStoredProcedure"
        .Parameters("@strParam1") = strFunctionParameter1
        .Parameters("@bolParam2") = bolFunctionParameter2
        .Execute 
 End With

MyResultSet.CursorLocation = adUseClient
MyResultSet.Open cmdCommand, , adOpenStatic, adLockReadOnly 

The command object 'cmdCommand' is executed the first time with the explicit call as the final line in the 'With' statement, '.Execute'.

What we found was that the last line: 'MyResultSet.Open cmdCommand...' is also implicitly executing the stored procedure a second time.

Since the stored procedure's function is essentially to activate and deactivate an alarm, by executing twice we were getting the activation and deactivation occurring at once and therefore no resultset returned.

Hopefully this might help avoid someone else getting stuck on something like this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文