Не удается перехватить SQL ошибок SP сервера, которые обходят попытку ... поймать в коде - PullRequest
0 голосов
/ 12 февраля 2020

У меня есть SQL хранимая процедура на сервере. Если я помещаю блок try вокруг кода, он только ловит определенные ошибки и вместо этого просто выводит некоторые ошибки в окно сообщений SSMS. Я полагаю, что в документации ( TryCatch ) говорится, что определенные блоки не обрабатываются определенными ошибками в блоке try..catch (например, при выборе из несуществующей таблицы)

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

Сообщение 207, уровень 16, состояние 1, процедура dbo.TestSP, строка 185 [Batch Start Line 2] Неверное имя столбца 'InvalidColumn'.

Однако я запускаю SP из кода, а не из SSMS, и не получаю никаких ошибок или исключений.

В частности, мой метод Command Execute просто возвращает без вызова исключения возвращаемое значение является пустым значением, и поэтому я абсолютно не знаю, что это за ошибка при ведении журнала или сообщении пользователю. Я также попытался полностью удалить блок try с теми же результатами.

Я использую ADODB старой школы в VBA, но тот же принцип применим к. Net Я посмотрел на свойства объекта Command и там кажется, там не так много, и возвращаемое состояние равно 0.

Есть ли способ отловить или найти эти ошибки где-нибудь в моих объектах Command или Connection, чтобы я мог их регистрировать, кроме простого сообщения «неизвестная ошибка» '?

В качестве примера моя хранимая процедура выглядит следующим образом, и оператор select с недопустимым столбцом вызывает ошибку, как показано выше, и не вызывает ошибку.

ALTER PROCEDURE [dbo].[TestSP]
AS
BEGIN
 SET NOCOUNT ON;
 BEGIN TRY
    declare @returnCode int;
    If object_id('syn_xxx','SN') is not null drop synonym syn_xxx
    exec('create synonym syn_xxx for sometable')
    SELECT TOP 1 InvalidColumn from syn_xxx
 END TRY
 BEGIN CATCH
     set @returnCode=ERROR_NUMBER()
 END CATCH
 return @returnCode
END     

Мой код это VBA и следующим образом. Коллекция Errors ничего не содержит, возвращаемое значение - пустая строка.

Dim conn_ As ADODB.Connection
Dim cmd As New ADODB.Command
Set conn_ = New ADODB.Connection
conn_.Open dsn
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "TestSP"
cmd.ActiveConnection = conn_
cmd.Execute

1 Ответ

0 голосов
/ 13 февраля 2020

Каким провайдером вы пользуетесь в dsn?

Private Sub CommandButton1_Click()

    Dim con As New ADODB.Connection
    Dim cmd As New ADODB.Command
    Dim errLoop As ADODB.Error
    Dim i As Integer
    Dim StrTmp As String


    'On Error GoTo AdoError
    On Error Resume Next

    con.ConnectionString = "Provider=SQLNCLI11;" _
             & "Server=(local);" _
             & "Database=master;" _
             & "Integrated Security=SSPI;"

    con.Open

    cmd.ActiveConnection = con
    cmd.CommandType = adCmdStoredProc
    cmd.CommandText = "TestSP"
    cmd.Execute

    MsgBox ("number of errors after procedure 'testproc'  --- " & con.Errors.Count)

    If con.Errors.Count > 0 Then

        i = 1

        ' Process
        StrTmp = StrTmp & vbCrLf & "VB Error # " & Str(Err.Number)
        StrTmp = StrTmp & vbCrLf & "   Generated by " & Err.Source
        StrTmp = StrTmp & vbCrLf & "   Description  " & Err.Description

        ' Enumerate Errors collection and display properties of
        ' each Error object.

        For Each errLoop In con.Errors
            With errLoop
                StrTmp = StrTmp & vbCrLf & "Error #" & i & ":"
                StrTmp = StrTmp & vbCrLf & "   ADO Error   #" & .Number
                StrTmp = StrTmp & vbCrLf & "   Description  " & .Description
                StrTmp = StrTmp & vbCrLf & "   Source       " & .Source
                i = i + 1
            End With
        Next

        MsgBox (StrTmp)

    End If

    cmd.CommandText = "select 10 as test"
    cmd.CommandType = adCmdText
    cmd.Execute
    MsgBox ("number of errors after 'select 10 as test'  --- " & con.Errors.Count)


    ' Close all open objects.
    If con.State = adStateOpen Then
        con.Close
    End If


End Sub
...