Хранимая процедура SQL Server 2005 с использованием табличной переменной не возвращает ResultSet в приложение VB6 - PullRequest
1 голос
/ 02 июля 2010

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

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

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

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

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

Я попытался перезапустить свой SQL Server (2005 версия 9.0.4053), перезагрузить компьютер, я попытался с включенным и выключенным 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: Мы только что обнаружили, что если мы создадим произвольную таблицу для хранения данных, которые будут возвращены последним оператором выбора вместо использования табличной переменной, процедура работает ...

1 Ответ

0 голосов
/ 06 июля 2010

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

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

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

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

...