从最初构建于SQL Server 2000中的这些年中,我们有一个旧产品已经慢慢向前推进,问题是SQL如何从RaiseError调用中唤醒错误。在调用存储过程中没有从触发器中显示RaiseError
比如我有对提出类似这样的错误表中的触发器:
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
值到它执行更新程序,使得程序的代码(更新声明和以下if @@ Error!= 0)可以保持不变吗?如果不是,那么这对我的应用程序是一个巨大的改变,因为我需要更改所有受影响表格更新的位置以及所有触发器。
我知道这是遗留代码,但是一旦你开始看到GOTO语句,就该卷起袖子并将您的代码从黑暗时代拉出来并开始使用TRY/Catch。十多年来,它已经成为一种更好的错误处理技术。 –
你发布的一小段代码中的其他巨大的代码味道是你始终有标量变量。这是一个很好的迹象表明你的触发器假设只有一行操作。他们需要重写为基于集合的方法来处理多行。 –
如果在'fatalerror:'之后引发另一个错误,该怎么办? – ughai