SQL Server 2005 中使用 Try Catch 处理异常
TRY...CATCH是SqlServer2005/2008令人印象深刻的新特性.提高了开发人员异常处理能力.没有理由不尝试一下Try..Catch功能.
*TRY块-包含可能产生异常的代码或脚本
*CATCH块-如果TRY块出现异常,代码处理流将被路由到CATCH块.在这里你可以处理异常,记录日志等.
SqlServer中的TryCatch和C#,JAVA等语言的处理方式一脉相承.这种一致性才是最大的创新之处.
一、SQLSERVER2000中异常处理
CREATEPROCusp_AccountTransaction @AccountNumINT, @AmountDECIMAL AS BEGIN BEGINTRANSACTION--beginningatransaction.. UPDATEMyCheckingSETAmount=Amount-@Amount WHEREAccountNum=@AccountNum IF@@ERROR!=0--check@@ERRORvariableaftereachDMLstatements.. BEGIN ROLLBACKTRANSACTION--RollBackTransactionifError.. RETURN END ELSE BEGIN UPDATEMySavingsSETAmount=Amount+@Amount WHEREAccountNum=@AccountNum IF@@ERROR!=0--check@@ERRORvariableaftereachDMLstatements.. BEGIN ROLLBACKTRANSACTION--RollBackTransactionifError.. RETURN END ELSE BEGIN COMMITTRANSACTION--finally,CommitthetransactionifSuccess.. RETURN END END END GO
上面是Sqlserver2000的一个存储过程,在每个数据库操作之后立即必须检查@@ERROR,进行Commit/RollBack该事务.
Sqlserver2000中监测错误,只能通过监测全局遍历@@ERROR.由于@@ERROR会被下一个数据库操作所覆盖.所以在每次操作完后必须立即监测.
二、SQLSERVER2005中异常处理
TRY...CATCH是SQLServer2005提供的更具有可读性的语法.每个开发人员都熟悉这种写法.SQLServer2005仍然支持@@ERROR这种用法.
1.trycatch语法:
BEGINTRY TryStatement1 TryStatement2 ... TryStatementM ENDTRY BEGINCATCH CatchStatement1 CatchStatement2 ... CatchStatementN ENDCATCH
2.获得错误信息的函数表:
下面系统函数在CATCH块有效.可以用来得到更多的错误信息:
函数 描述
ERROR_NUMBER() 返回导致运行CATCH块的错误消息的错误号。
ERROR_SEVERITY() 返回导致CATCH块运行的错误消息的严重级别
ERROR_STATE() 返回导致CATCH块运行的错误消息的状态号
ERROR_PROCEDURE() 返回出现错误的存储过程名称
ERROR_LINE() 返回发生错误的行号
ERROR_MESSAGE() 返回导致CATCH块运行的错误消息的完整文本
简单示例:
BEGINTRY SELECTGETDATE() SELECT1/0--Evergreendividebyzeroexample! ENDTRY BEGINCATCH SELECT'Therewasanerror!'+ERROR_MESSAGE() RETURN ENDCATCH;
3.trycatch回滚/提交事务的示例
ALTERPROCusp_AccountTransaction @AccountNumINT, @AmountDECIMAL AS BEGIN BEGINTRY--StarttheTryBlock.. BEGINTRANSACTION--Startthetransaction.. UPDATEMyCheckingSETAmount=Amount-@Amount WHEREAccountNum=@AccountNum UPDATEMySavingsSETAmount=Amount+@Amount WHEREAccountNum=@AccountNum COMMITTRAN--TransactionSuccess! ENDTRY BEGINCATCH IF@@TRANCOUNT>0 ROLLBACKTRAN--RollBackincaseofError --youcanRaiseERRORwithRAISEERROR()Statementincludingthedetailsoftheexception RAISERROR(ERROR_MESSAGE(),ERROR_SEVERITY(),1) ENDCATCH END GO
三、实例讲解
创建错误日志表:
CREATETABLEErrorLog(errNumINT,ErrSevNVARCHAR(1000),ErrStateINT,ErrProcNVARCHAR(1000),ErrLineINT,ErrMsgNVARCHAR(2000))
创建错误日志记录存储过程:
CREATEPROCEDUREErrorLog AS SELECTERROR_NUMBER()ASErrNum,ERROR_SEVERITY()ASErrSev,ERROR_STATE()ASErrState,ERROR_PROCEDURE()ASErrProc,ERROR_LINE()ASErrLine,ERROR_MESSAGE()ASErrMsg INSERT INTOErrorLog VALUES(ERROR_NUMBER(),ERROR_SEVERITY(),ERROR_STATE(),ERROR_PROCEDURE(),ERROR_LINE(),ERROR_MESSAGE()) GO
写一个存储过程吧!里面使用一下TryCatch:
USE[Your_Test] GO /******Object:StoredProcedure[dbo].[getTodayBirthday] ScriptDate:05/17/201015:38:46 Author:jinho Desc:获取当天生日的所有人 ******/ SETANSI_NULLSON GO SETQUOTED_IDENTIFIERON GO ALTERPROCEDURE[dbo].[getTodayBirthday] AS BEGINTRY declare@todaydatetime; SET@today=GETDATE();--获取今天的日期 DECLARE@dayVARCHAR(2); SET@day=REPLACE(DAY(@today),0,''); DECLARE@monthVARCHAR(2); SET@month=REPLACE(month(@today),0,''); DECLARE@yearVARCHAR(4); SET@year=YEAR(@today); SELECT*FROMdbo.UserInfoWHEREREPLACE(DAY(CONVERT(DATETIME,Birthday)),0,'')=@dayANDREPLACE(MONTH(CONVERT(DATETIME,Brithday)),0,'')=@monthANDBirthdayISNOTNULL ENDTRY BEGINCATCH ErrorLog--调用上面的存储过程,保存错误日志 ENDCATCH
说明:ERROR_NUMBER(),ERROR_SEVERITY(),ERROR_STATE(),ERROR_PROCEDURE(),ERROR_LINE(),ERROR_MESSAGE()这几个函数只能用在Catch里面!