У нас есть старый продукт, который медленно двигался вперед с тех пор, как он был первоначально построен в SQL Server 2000, и проблема связана с тем, как SQL создает пузырьки ошибок из вызовов RaiseError.RaiseError, не отображающийся в Trigger in Calling Сохраненная процедура
Например у меня есть триггер на таблицу, которая вызывает ошибку, подобную этой:
ALTER TRIGGER [dbo].[Rotation_UTrig]
ON [dbo].[Rotation] FOR UPDATE AS
BEGIN
SET NOCOUNT ON
.
.
.
/* * VALIDATION RULE FOR FIELD 'RotationYear' */
RAISERROR ('Invalid value entered for RotationYear, must be >=0', 44444, 1)
goto fatalerror
.
.
fatalerror:
END
Это имеет необходимый эффект в вызывающей процедуре, что если оператор имеет значение для @@Error
:
update Rotation
set OrderedQuantity = @OrderedQuantity,
DespatchedQuantity = @DespatchedQuantity
where ID = @RotationNo
if @@Error != 0
begin
if @AlreadyInTrans = 0 begin rollback transaction end
raiserror ('Error on update of Rotation.', 16, 1)
goto fatalerror
end
.
.
.
fatalerror:
но ошибка видела вызывающее приложение родителя:
Error Severity levels greater than 18 can only be specified by members of the sysadmin role, using WITH LOG option
Это происходит потому, что уровень ошибки в триггере 44444, если добавить
With LOG
в код триггера для Raiserror
то это закрывает соединение (которое мы не хотим). Если я понизить уровень ошибки до 16 в триггере, то
if @@Error !=0
линия не попал в @@Error
устанавливается равным нулю.
Другой, чем при использовании
Try... Catch
вокруг обновления заявления в родительском порядке, есть ли другой способ пузыриться значение @@Error
в процедуру, которая делает обновление, так что процедура кода (обновление утверждение и следующее, если @@ Error! = 0) может оставаться неизменным? Если нет, то это огромное изменение для моего приложения, так как мне нужно будет изменить все места, где обновляются обновленные таблицы, а также все триггеры.
Я знаю, что это устаревший код, но как только вы начинаете видеть инструкцию GOTO, пришло время свернуть рукава и вытащите свой код из темных веков и начните использовать TRY/Catch. Он был доступен в качестве более совершенной техники обработки ошибок уже более десяти лет. –
Другим огромным запахом кода в небольшом фрагменте кода, который вы опубликовали, является то, что у вас есть скалярные переменные. Это довольно хороший признак того, что триггеры предполагают, что будет только операция с одной строкой. Они должны быть переписаны как основанный на наборе подход для обработки нескольких строк. –
что делать, если вы вызываете еще одну ошибку после 'fatalerror:'? – ughai