Как предоставить больше информации о сбое хранимого процесса в агенте SQL - PullRequest
0 голосов
/ 11 марта 2011

У меня есть настройка задания агента SQL, и в этом задании есть шаг для выполнения сохраненного процесса.Если этот сохраненный процесс завершится неудачей, задание агента SQL отобразит сообщение об ошибке, но другой информации нет.Что-то вроде трассировки стека или, по крайней мере, сохраненного процесса, который выполнялся, и номер строки был бы очень полезен.

Например, если выполняется следующий сохраненный процесс, появляется сообщение об ошибке типа «Выполнено как пользователь: NT AUTHORITY \ NETWORKСЕРВИС. Запуск [SQLSTATE 01000] (сообщение 0) Недопустимое имя объекта «NonExistentTable». [SQLSTATE 42S02] (Ошибка 208). Шаг не выполнен. "без указания, где именно произошла ошибка.

CREATE PROCEDURE TestSpLogging AS 
BEGIN
PRINT 'Start'
SELECT * FROM NonExistentTable
PRINT 'End'
END

Каков наилучший способ раскрытия этой информации?

Ответы [ 2 ]

2 голосов
/ 11 марта 2011

Использование подхода, описанного в http://www.sommarskog.se/error_handling_2005.html, похоже, пока работает достаточно.Требуется только обновление хранимой процедуры верхнего уровня, и она выведет имя хранимой процедуры, которая завершилась ошибкой, и номер строки для агента SQL.

Ошибка вывода будет выглядеть следующим образом:

Выполнено от имени пользователя: NT AUTHORITY \ NETWORK SERVICE.*** [InnerInnerStoredProc2], 5. Errno 208: недопустимое имя объекта «NonExistentTable».[SQLSTATE 42000] (ошибка 50000) Запустите [SQLSTATE 01000] (ошибка 0).Шаг не выполнен.

Сводка шагов:

Создайте следующую хранимую процедуру обработчика ошибок:

CREATE PROCEDURE error_handler_sp AS

DECLARE @errmsg   nvarchar(2048),
        @severity tinyint,
        @state    tinyint,
        @errno    int,
        @proc     sysname,
        @lineno   int

SELECT @errmsg = error_message(), @severity = error_severity(),   -- 10
       @state  = error_state(), @errno = error_number(),
       @proc   = error_procedure(), @lineno = error_line()

IF @errmsg NOT LIKE '***%'                                        -- 11  
BEGIN 
   SELECT @errmsg = '*** ' + coalesce(quotename(@proc), '<dynamic SQL>') + 
                    ', ' + ltrim(str(@lineno)) + '. Errno ' + 
                    ltrim(str(@errno)) + ': ' + @errmsg
   RAISERROR(@errmsg, @severity, @state)
END
ELSE
   RAISERROR(@errmsg, @severity, @state)
go

Оберните хранимый процесс верхнего уровня в триггере try следующим образом

BEGIN TRY
   SET NOCOUNT ON
   SET XACT_ABORT ON

EXEC InnerStoredProc1
EXEC InnerStoredProc2

END TRY
BEGIN CATCH
   IF @@trancount > 0 ROLLBACK TRANSACTION
   EXEC error_handler_sp
   RETURN 55555
END CATCH
1 голос
/ 11 марта 2011

Один из способов сделать это - добавить обработку хранимой процедуры.Вот простой метод, который мы используем, вот что-то вроде этого

declare
    @Error                 int
   ,@ErrorMsg              varchar(1000)
   ,@StepName              varchar(500)
   ,@ProcedureName         sysname
   ,@dtDateTime            datetime

select @ProcedureName = object_name(@@procid)

begin try
select @StepName = 'Step 01: Select from table
PRINT 'Start'
SELECT * FROM NonExistentTable
PRINT 'End'

end try

begin catch
   select @Error = @@ERROR
   set @ErrorMsg = @ProcedureName + ' Error: ' + @StepName
                                  + ', dbErrorNbr:' + IsNull(convert(varchar(10),@Error),'Null')
   raiserror (@ErrorMsg, 16, 1) with nowait
end catch
...