Chinaunix首页 | 论坛 | 博客
  • 博客访问: 665574
  • 博文数量: 245
  • 博客积分: 4732
  • 博客等级: 上校
  • 技术积分: 3102
  • 用 户 组: 普通用户
  • 注册时间: 2007-11-02 14:31
文章分类

全部博文(245)

文章存档

2012年(1)

2011年(42)

2010年(132)

2009年(59)

2008年(11)

我的朋友

分类: WINDOWS

2011-03-22 16:07:01

 
 
深入理解SQL Server 中的错误处理大多数迭代语言编译器都有内置的错误处理程序(例如,TRY…CATCH语句),开发者们在设计代码的时候可以利用它们。虽然SQL Server 2000的开发者不能够像迭代语言的开发者那样利用内置的工具,但是他们可以用系统变量@@ERROR来设计自己有效的错误处理工具。

引入事务

为了能够掌握在SQL Server 2000中错误处理是如何工作的,你必须首先要理解数据库事务的概念。在数据库术语中,事务就是指作为一个单独的工作单位出现的一系列语句。举个例子来说,假设你有三个语句要执行,事务就可以这样被设计,要么所有三个语句都成功发生,否则就一个都不发生。

在SQL Server中执行数据处理操作时,操作是在缓冲存储器中发生的,并不是立即被写入实际的表格中。然后,当SQL Server运行CHECKPOINT进程时,已经发生的变化才被写入磁盘。这也就意味着,在事务发生的过程中,变化并不被写入磁盘,直到它被提交了,才会被写入。运行时间较长的事务需要更多的处理存储空间,需要数据库保持更长时间的锁定。所以当你在工作环境中设计运行时间长的事务时,一定要小心。

下面是一个很好的例子,说明了利用事务的好处。从ATM中取钱需要以下几个步骤:输入一个PIN号码,选择一个帐户类型和输入你想要提取的资金的金额。如果你试图从ATM中取出50美元,然后操作失败,你肯定不愿意在没有拿到钱的情况下被扣除50美元。事务就可以被用来保证这种一致性。

SQL Server 2000中成功的错误处理需要始终如一地检查系统变量@@ERROR 的值。@@ERROR是指在所有语句在给定的连接下,在服务器上被执行以后,由SQL Server数据库引擎更新的一个变量。这个变量中包括了相应的错误号码,如果有的话。你可以在主数据库的sysmessages表格中找到这些错误号码的列表。关于这个表格的详细资料在微软的网站上已经被列出。

下面是一个说明变量@@ERROR如何工作的例子:


PRINT 'Taking a look at @@ERROR'
PRINT @@ERROR

在这些指令中,我们将在屏幕上显示一个字符串,并输出变量@@ERROR的值。因为屏幕上输出的没有错误,所以@@ERROR的值为0。


PRINT 1/0
PRINT @@ERROR

在上面这个例子中,我们发生了用0作除数的错误,这样变量@@ERROR中将包括数字8134,它是微软给这种错误分配的错误代号。对于大多数错误处理来说,只有当@@ERROR的值不为0时,即显示有错误发生的时候,你才会关注到它。在记录错误的时候,留意每个错误号码不失为一个好办法,因为这样的话,在调试过程中,调用它们就很方便了。

工作中的错误处理

下面是一个关于怎样在存储过程中利用错误处理的例子。示例脚本的目的是要执行一个存储过程,定义一个事务,然后在一个表格中插入一条记录。因为只是为了解释说明的目的,所以我们用以下的方式设计该程序,这样就可以知道到底是提交还是重新运行该项事务。

执行下面的语句来创建我们在例子将要用到的表格:


CREATE TABLE Transactions
(
      TranID SMALLINT IDENTITY(1,1) PRIMARY KEY,
      EntryDate SMALLDATETIME DEFAULT(GETDATE()),
      ParamValue CHAR(1),
      ThrowError BIT
)

脚本中的两个字段值是ParamValue和ThrowError。这些字段将与我们要创建的程序中的输入参数相对应,并且我们将在提交事务的逻辑中用到它们。

一旦用来记录事务的表格准备就绪之后,我们就要开始创建程序了。这个程序中将有一个用来简单记录字符值和参量的参数,它将使我们能够指出程序中的错误。运行列表A中的语句可以创建这个程序。


CREATE PROCEDURE usp_TestTransaction

(
@ParamValue CHAR(1),
@ThrowError BIT = 0

)

AS

BEGIN
DECLARE @ErrorCode INT

BEGIN TRANSACTION

INSERT INTO Transactions (ParamValue, ThrowError)
VALUES(@ParamValue, @ThrowError)

IF @ThrowError = 1
RAISERROR ('A custom error has been thrown.', 16, 1)


SET @ErrorCode = @@ERROR


IF @ErrorCode <> 0
GOTO ErrorHandler
ELSE
BEGIN
COMMIT TRAN
RETURN(0)
END

ErrorHandler:
BEGIN
ROLLBACK TRANSACTION
RETURN(1)
END

END

GO


列表A

这个简单的存储过程展示了有效的错误处理必须具备的特征。首先,要明确定义一个事务。然后当一条记录插入事务表格之后,我们再检查参数@ThrowError的值。该参数显示是否有错误发生,再用函数RAISERROR来指出自定义的错误。当函数RAISERROR被调用时,变量@@ERROR的值显示的就是我们所提供错误的号码。

如果在存储过程中有错误发生,我们将重新运行所执行的事务。重新运行事务就意味着我们尝试插入事务表格的记录将会被移除,就像从来没有发生过一样。数据库的状态将与事务开始之前完全保持一致。

在这个例子中,你同样会注意到GOTO语句和ErrorHandler标签的使用。通常,使用GOTO语句在迭代编程语言中被认为是一种不好的编程习惯,但是在SQL Server 2000错误处理时,它们就非常有用了。不要害怕用GOTO语句来处理错误。

下面这个程序调用将出现错误,记录将不会被插入事务表格中:


DECLARE @ReturnCode INT
EXECUTE @ReturnCode = usp_TestTransaction @ParamValue = 'E', @ThrowError = 1
PRINT @ReturnCode

下面这个程序调用将不会出现错误,插入的记录将被提交到事务表格:


DECLARE @ReturnCode INT
EXECUTE @ReturnCode = usp_TestTransaction @ParamValue = 'S', @ThrowError = 0
PRINT @ReturnCode

这些程序调用利用了参数Return,它能够显示出一个存储过程的成功与否。在你的代码中明确设置参数Return,来显示程序运行是否成功是一个很好的编程习惯。这样,当存储过程失败的时候,你可以得知,并采取必要的措施来处理。例如,你可以嵌套程序调用和事务。你的应用可以潜在地定义一个事务,调用一个存储过程和提交或回滚外部事务(取决于存储过程的成败)。

放眼未来

SQL Server 2000中有效的错误处理的关键在于细致的事务设计和始终对变量@@ERROR 的值的检查。在日后的文章中,我将向你说明如何在SQL Server 2005中利用TRYCATCH语句的错误处理新能力。

 

阅读(934) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~