Хранимая процедура SQL Server 2005 с использованием переменной таблицы не возвращает ResultSet в приложение VB6

У меня есть хранимая процедура, которая выбирает одно поле из одной строки (на основе условного оператора) и сохраняет его в локальной переменной. На основе значения этого поля я обновляю то же поле в той же строке таблицы (используя тот же условный оператор). Таким образом, процедура сначала выполняет выбор в локальной переменной, а затем обновляет то же поле той же строки. Затем процедура возвращает набор результатов с помощью выбора переменной таблицы (я также попытался использовать временную таблицу). Набор результатов не содержит обновленной переменной или поля. Он даже не включает поля из этой таблицы.

Процедура работает правильно при вызове либо из Management Studio, либо из тестового приложения C #. Однако при вызове из моего приложения VB6 набор результатов не возвращается. Однако все обновления базы данных по-прежнему выполняются.

Я пробовал писать хранимую процедуру с транзакцией и без, с TRY ... CATCH и без, и то и другое одновременно. Я пробовал различные комбинации изоляции транзакций. Никаких исключений не создается, и транзакция всегда фиксируется. Я также использовал подсказку WITH (NOLOCK) для оператора select. Если я опущу обновление таблицы, это сработает. Если я оставлю присвоение локальной переменной и вместо этого жестко запрограммирую значение, оно будет работать. Если я просто использую select, где я бы поместил переменную, это НЕ будет работать.

Интересно, что если я добавлю в процедуру какой-нибудь оператор случайного выбора, он вернет этот набор результатов. Я даже могу без проблем выбрать то же поле из той же записи, которую я назначаю своей переменной. Но он все равно не вернет желаемый результат.

Мой набор результатов - это выборка из табличной переменной, которая заполняется с помощью операторов вставки с использованием переменных, установленных на протяжении всей процедуры. Объединений таблиц нет вообще. Я передаю процедуре 2 параметра, один из которых используется в моем условном операторе в исходном выборе. Но я все равно получаю такое же поведение, когда опускаю как параметры, так и значения жесткого кода.

Я попытался перезапустить свой SQL Server (версия 9.0.4053 2005 года), перезапустить свой компьютер, я попытался включить и выключить NOCOUNT, у меня в основном нет идей.

Изменить - Подробная информация о вызове 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: мы только что обнаружили, что если мы создадим произвольную таблицу для хранения данных, которые должны быть возвращены последним оператором выбора, вместо использования табличной переменной, процедура будет работать ...


person Span    schedule 02.07.2010    source источник
comment
Не могли бы вы добавить код SQL и VB? Я использую переменные таблицы в хранимых процессах, вызываемых VBA ...   -  person gbn    schedule 02.07.2010
comment
Или, по крайней мере, сохраненная подпись процесса и вызов VB ...   -  person gbn    schedule 02.07.2010


Ответы (1)


Мы обнаружили, что хранимая процедура на самом деле выполнялась дважды из-за способа ее вызова из 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', '.Execute'.

Мы обнаружили, что последняя строка: «MyResultSet.Open cmdCommand ...» также неявно выполняет хранимую процедуру во второй раз.

Поскольку функция хранимой процедуры состоит в том, чтобы активировать и деактивировать тревогу, при двойном выполнении мы получали активацию и деактивацию сразу, и поэтому набор результатов не возвращался.

Надеюсь, это поможет избежать того, чтобы кто-то еще застрял в чем-то подобном.

person Span    schedule 06.07.2010