Обработка ошибок - Определите, был ли sp_executesql источником - PullRequest
1 голос
/ 26 апреля 2019

Когда сообщение об ошибке возвращается sp_executesql, есть ли какой-либо встроенный метод / механизм обработки ошибок, который можно использовать для определения того, что эта ошибка была возвращена этой процедурой, а не непосредственно из содержащего сценария?

В случае ниже, подробности ошибки идентифицируют ошибку как возникшую в строке 1, но они не указывают, что ссылка на строку 1 не строка 1 из сценариясама , а точнее строка 1 в запросе, переданном сценарием на sp_executesql.

Я ищу способ идентифицировать источник, чтобы я мог соответствующим образом его зарегистрировать.Я хотел бы записать что-то вроде Script x - Call to inner query errored on that query's line 1 вместо общего (и вводит в заблуждение) Script x errored on line 1.

Демо

-- do other things first

BEGIN TRY  
    EXECUTE sp_executesql @stmt = N'SELECT 1/0';
END TRY
BEGIN CATCH  
    SELECT ERROR_NUMBER() AS ErrorNumber
         ,ERROR_SEVERITY() AS ErrorSeverity
         ,ERROR_STATE() AS ErrorState
         ,ERROR_PROCEDURE() AS ErrorProcedure
         ,ERROR_LINE() AS ErrorLine
         ,ERROR_MESSAGE() AS ErrorMessage
END CATCH; 

Возвращает:

ErrorNumber ErrorSeverity ErrorState  ErrorProcedure 
----------- ------------- ----------- ---------------
8134        16            1           NULL           

Ответы [ 2 ]

0 голосов
/ 27 апреля 2019

К сожалению, стек вызовов недоступен при обработке ошибок T-SQL. Чтобы упростить сбор сведений о стеке T-SQL, рассмотрите возможность запроса этой функции .

В приведенном ниже примере используется вложенный TRY / CATCH, чтобы вызвать пользовательскую ошибку (сообщение номер 50000) при возникновении ошибок внутреннего сценария, фиксируя доступные подробности вместе с описанием контекста («внутренний сценарий»). При возникновении ошибок во внешнем скрипте исходная ошибка просто перебрасывается. Отсутствие контекста и номер системной ошибки указывают на ошибку самого внешнего сценария, хотя вместо этого можно создать и вызвать пользовательскую ошибку, включая описание внешнего контекста сценария.

BEGIN TRY
    BEGIN TRY

        EXECUTE sp_executesql @stmt = N'SELECT 1/0;';
    END TRY
    BEGIN CATCH  

        DECLARE
             @ErrorNumber int
            ,@ErrorMessage nvarchar(2048)
            ,@ErrorSeverity int
            ,@ErrorState int
            ,@ErrorLine int;

        SELECT
             @ErrorNumber =ERROR_NUMBER()
            ,@ErrorMessage =ERROR_MESSAGE()
            ,@ErrorSeverity = ERROR_SEVERITY()
            ,@ErrorState =ERROR_STATE()
            ,@ErrorLine =ERROR_LINE();

        RAISERROR('Error %d caught in inner script at line %d: %s'
            ,@ErrorSeverity
            ,@ErrorState
            ,@ErrorNumber
            ,@ErrorLine
            ,@ErrorMessage);

    END CATCH; 
END TRY
BEGIN CATCH  

    THROW;

END CATCH; 
GO
0 голосов
/ 26 апреля 2019

вы можете использовать sp_executeSQL OUTPUT параметр :

DECLARE @ErrorLine NVARCHAR(32)
DECLARE @Params NVARCHAR(150) = '@Return INT OUTPUT'
DECLARE @SQL NVARCHAR(MAX) = ''


SET @SQL = @SQL + '     '
SET @SQL = @SQL + '    BEGIN TRY '
SET @SQL = @SQL + '        SELECT 100 AS First '
SET @SQL = @SQL + '        SELECT 1/0 AS Second '
SET @SQL = @SQL + '    END TRY '
SET @SQL = @SQL + '    BEGIN CATCH '
SET @SQL = @SQL + '        SELECT @Return = ERROR_LINE() '
SET @SQL = @SQL + '    END CATCH '
SET @SQL = @SQL + '     '

EXEC sp_executeSQL @SQL, @Params, @Return = @ErrorLine OUTPUT

SELECT @ErrorLine

этот код будет отображать @ErrorLine = 1 независимо от того, где ошибка, потому что технически весь SQLнаходится на одной строке, и это делает все это более сложным, но вы понимаете ...

РЕДАКТИРОВАТЬ: если @ErrorLine равно NULL, в sp_executeSQL.

ошибки нет.
...