#sql-server-2008 #tsql
#sql-server-2008 #tsql
Вопрос:
В следующей процедуре, которую я нашел здесь:
ALTER PROCEDURE [dbo].[usp_RethrowError]
AS -- Return if there is no error information to retrieve.
IF ERROR_NUMBER() IS NULL
RETURN;
DECLARE @ErrorMessage NVARCHAR(4000),
@OriginalErrorNumber INT,
@RethrownErrorNumber INT,
@ErrorSeverity INT,
@ErrorState INT,
@ErrorLine INT,
@ErrorProcedure NVARCHAR(200);
-- Assign variables to error-handling functions that
-- capture information for RAISERROR.
SELECT
@OriginalErrorNumber = ERROR_NUMBER()
,@ErrorSeverity = ERROR_SEVERITY()
,@ErrorSeverity = ERROR_SEVERITY()
,@ErrorState = ERROR_STATE()
,@ErrorLine = ERROR_LINE()
,@ErrorProcedure = ISNULL(ERROR_PROCEDURE(),'-');
--Severity levels from 0 through 18 can be specified by any user.
--Severity levels from 19 through 25 can only be specified by members of the sysadmin fixed server role or users with ALTER TRACE permissions
IF @OriginalErrorNumber < 19
SET @RethrownErrorNumber = @OriginalErrorNumber
ELSE
SET @RethrownErrorNumber = 18
-- Building the message string that will contain original
-- error information.
SELECT
@ErrorMessage = N'Error %d, Level %d, State %d, Procedure %s, Line %d, ' 'Message: ' ERROR_MESSAGE();
-- Raise an error: msg_str parameter of RAISERROR will contain
-- the original error information.
RAISERROR (@ErrorMessage,
@ErrorSeverity,
@ErrorState,
@RethrownErrorNumber, -- parameter: original error number or 18, if the original was >=19.
@ErrorSeverity, -- parameter: original error severity.
@ErrorState, -- parameter: original error state.
@ErrorProcedure, -- parameter: original error procedure name.
@ErrorLine -- parameter: original error line number.
);
Кто-нибудь может объяснить следующую строку:
SELECT
@ErrorMessage = N'Error %d, Level %d, State %d, Procedure %s, Line %d, ' 'Message: ' ERROR_MESSAGE();
Я понимаю, что вхождения % являются заполнителями для целых чисел со знаком (%d) и strinf (%s), но я не понимаю, какие переменные сопоставлены этим заполнителям. Похоже, они не соответствуют параметрам, указанным в вызове RAISERROR:
RAISERROR (@ErrorMessage,
@ErrorSeverity,
@ErrorState,
@RethrownErrorNumber, -- parameter: original error number or 18, if the original was >=19.
@ErrorSeverity, -- parameter: original error severity.
@ErrorState, -- parameter: original error state.
@ErrorProcedure, -- parameter: original error procedure name.
@ErrorLine -- parameter: original error line number.
);
Я внес два небольших изменения в подпрограмму, одно для снижения серьезности, если> 19, а другое для использования исходного состояния вместо того, чтобы всегда передавать 1.
Если вы, ребята, не слишком сильно испортите эту процедуру моими незначительными изменениями, я добавлю информацию об ошибке протоколирования в пользовательскую таблицу непосредственно перед повторным переносом.
Для вызова:
DECLARE @Zero INT
SET @Zero = 0
BEGIN TRY
SELECT 5 / @Zero
END TRY
BEGIN CATCH
PRINT 'We have an error...'
EXEC usp_RethrowError
END CATCH
Последующие вопросы:
1) В ссылке выше упоминается, что эта процедура не будет работать при взаимоблокировках. Есть причина, почему?
2) Я добавил часть «ЕСЛИ @OriginalErrorNumber < 19». Я не слишком обеспокоен тем, что при возникновении ошибки > 18 повторное удаление ошибки будет иметь степень серьезности 18. В любом случае я нажимаю на прерывание, и первоначальная серьезность будет зарегистрирована. Есть ли что-нибудь еще в этой процедуре, о чем мне нужно беспокоиться?
Комментарии:
1. Примечание сбоку: возможно, что в нем
ERROR_MESSAGE()
будут некоторыеprintf()
строки подстановки в стиле, такие как%s
. Я бы рекомендовал передать,ERROR_MESSAGE()
используя'Message: %s'
и включивERROR_MESSAGE()
в конце списка аргументов вашего новогоRAISERROR()
вызова, потому что в противном случае любые символы подстановки вprintf()
стиле вERROR_MESSAGE()
будут заменены TSQL на строку(null)
, когда символы подстановки должны передаваться без подстановки.
Ответ №1:
Надеюсь, это поможет!
Вы на правильном пути, ErrorMessage — это строка шаблона, которая используется RAISERROR. Рассмотрение грамматической структуры RAISERROR устранит путаницу:
RAISERROR ( { msg_id | msg_str | @local_variable }
{ ,severity ,state }
[ ,argument [ ,...n ] ] )
[ WITH option [ ,...n ] ]
Первыми тремя обязательными аргументами являются строка шаблона сообщения (msg_str), серьезность и состояние. За ними следуют необязательные аргументы, которые заменят параметры подстановки в msg_str.
Таким образом, код позволяет:
msg_str быть сообщением об ошибке
серьезность — это серьезность ошибки
состояние будет ErrorState
в качестве аргументов могут использоваться RethrownErrorNumber, ErrorSeverity, ErrorState, ErrorProcedure, ErrorLine
Ссылка http://msdn.microsoft.com/en-us/library/ms178592.aspx
Комментарии:
1. Я думаю, что заполнители % соответствуют указанным вами аргументам , начиная с 4-го параметра@RethrownErrorNumber, который я передаю в процедуру RAISERROR. Первые 3 параметра должны служить только для повторного удаления ошибки. Заполнители относятся соответственно к параметрам аргумента (4-й параметр и далее).) Спасибо!