SQL Server 中的错误处理(一)
Sql server 2000 中的错误处理
Sql server 2000中所提供的是一种非结构化的错误处理,其主要方法是使用@@error 来取得之前最近的一条处理的返回值。0表示操作成功,非0值则表示操作失败,不同的非0值表示不同的错误。
@@error 使用不方便之处在于你必须在怀疑会出错的语句之后,立即将@@error 赋予能够长时间保存值的自定义变量,否则该值将随着下一条语句的执行而产生变化,无法反映你所关注语句的真实执行情况。返回上一语句所影响的行数的@@rowcount亦是如此。
于是我们想,如果执行某操作后需要同时返回@@error以及@rowcount,是否可以运用下列语句?
<sql operation>
SET @err = @@error
SET @rc = @@rowcount
答案是否定的,问题在于第二句 “SET @rc = @@rowcount;” 返回的实为 “SET @err = @@error” 的执行结果(为0 — 该语句未影响任何一行) 而并非我们所希望得到的 <sql operation> 的属性。所以我们看出,单句赋值的SET是不能达到预期结果的。
不过在Sql server 2000中,我们还有一个work around:
<sql operation>
SELECT @err = @@error, @rc = @@rowcount
– Error handling code here
这样一来,语句段的错误处理我们可以解决了,接下来我们来看看存储过程。我们不妨把存储过程看成一个方法,都有参数有返回值。如果我们在一个方法中需要传出两个输出,那么我们应该怎么做?只能把其中一个作为out参数。存储过程也是如此:
CREATE PROC dbo.usp_XXXX
@parameter VARCHAR(50),
@rows INT OUTPUT
AS
DECLARE @err AS INT
<Sql operations>
SELECT @err = @@error, @rows = @@rowcount
RETURN @err
GO
虽然有一些不方便,不过还是能够处理。那么我们再来看看一些不能处理的情况,在Sql server 2000中,你并不能捕获到所有的错误。有一些错误会导致Sql语句执行直接中止,根本无法进入到之后基于判断@@error的错误处理:
1. 除零错误
SELECT 1/0; — 出错后直接中断
PRINT ‘I’m here’; — 该句不会执行
2. 转型错误
SELECT 1 + ‘A’ — 出错后直接中断
PRINT ‘I’m here’; — 该句不会执行
3. 解析编译错误
SELECT * FROM dbo.nonexistingtable; — 出错后直接中断
PRINT ‘I’m here’; — 该句不会执行
除了上述无法处理的错误之外,即便你能得到@@error,它也只是一个INT值,记录错误编号,除此之外,不包含任何其他信息。
附:Sql server 2000中常用的错误处理模板,以存储过程为例
CREATE PROC dbo.usp_XXXX
@parameter VARCHAR(50),
@rows INT OUTPUT
AS
DECLARE @originalTrancount INT
SET @originalTrancount = @@TRANCOUNT
IF @originalTrancount = 0
BEGIN
BEGIN TRAN
END
<Operation in TRAN>
SELECT @err = @@error, @rows == @@rowcount
Quit:
IF @originalTrancount = 0
BEGIN
IF @err = 0
COMMIT TRAN
ELSE
ROLLBACK TRAN
END
RETURN @err