0

0

SQL 2005 try catch 的详细介绍

PHP中文网

PHP中文网

发布时间:2017-04-01 16:19:36

|

1685人浏览过

|

来源于php中文网

原创

1         TRY…CATCH

1.1   用法

TRY…CATCH的语法如下:

BEGIN TRY            -- TRY 模块
       -- 业务处理
END TRY
BEGIN CATCH          -- CATCH 模块
       -- 错误处理
END CATCH

BEGIN TRYEND TRY中的是TRY模块; BEGIN CATCHEND CATCH之间是CATCH模块。TRY模块中的任何一条T-SQL出错时,将跳到CATCH模块(TRY模块中,出错的T-SQL后的语句不会被执行)。

1.2   错误处理函数

使用TRY…CATCH时,必须在CATCH模块中对错误处理处理,如果不处理,则SQL Server不会给出任何提示,这样就不会知道是否有错误发生。

CATCH模块中,可以使用下面的这些函数来实现错误处理(这些函数只能用在CATCH模块中),在其他位置使用时,这些函数返回NULL值。

n   ERROR_NUMBER() 返回错误号

n   ERROR_MESSAGE() 返回错误消息的完整文本。此文本包括为任何可替换参数(如长度、对象名或时间)提供的值

n   ERROR_SEVERITY() 返回错误严重性

n   ERROR_STATE() 返回错误状态

n   ERROR_LINE() 返回导致错误的例程中的行号

n   ERROR_PROCEDURE() 返回出现错误的存储过程触发器的名称

1.3   使用TRY…CATCH时的注意事项

使用TRY…CATCH时,需要注意下述事项:

n   CATCH模块必须紧跟在TRY模块之后

n   TRY…CATCH构造可以嵌套。这意味着可以将TRY…CATCH构造放置在其他TRY模拟和CATCH模块内。当嵌套的TRY块中出现错误时,程序控制将传递到与嵌套的TRY块关联的CATCH

n   严重性为10或更低的错误被视为警告或信息性消息,这种错误不会导致处理跳到CATCH模块(通过RAISERROR抛出的自定义错误同样适用于此规则)。参考下面的T-SQL代码段进行测试。

BEGIN TRY
       -- 业务处理
       RAISERROR('start', 10, 1)     -- 此句不会导致处理转到CATCH 模块
       RAISERROR('warning', 11, 1)   -- 此句会导致处理转到CATCH 模块
       RAISERROR('finish', 10, 1)    -- 由于上一句导致处理转到CATCH 模块, 故此句不会被执行
END TRY
BEGIN CATCH
       -- 错误处理
       SELECT
              ERROR_MESSAGE()  -- 返回warning
END CATCH

2         TRY…CATCH and Transaction

2.1   XACT_STATE()函数

一般在TRY…CATCH中使用事务时,会在TRY模块提交(COMMIT)事务;而在CATCH块回滚(ROLLBACK)事务。

如果要准确的控制事务的提交和回滚,则可以通过XACT_STATE()函数判断当前事务的状态,以进一步确定如何进行事务处理。

XACT_STATE()函数在SQL Server 2005及其之后的版本中可用,该函数返回下列值:

n   0   当前请求没有活动的用户事务

n   1   当前请求有活动的用户事务。请求可以执行任何操作,包括写入数据和提交事务

n   -1  当前请求具有活动的用户事务,但法提交事务或回滚到保存点;它只能请求完全回滚事务

2.2   嵌套事务与事务保存点

SQL Server中的事务处理可以嵌套。可以通过全局变量@@TRANCOUNT查询当前连接的活动事务数(也就是事务嵌套的层数)。如果该变量值为0,则表示当前连接没有启用任何事务;如果该变量值>1,则表示当前连接存在事务嵌套。

SQL Server自动维护全局变量@@TRANCOUNT的值。当使用BEGIN TRANSACTION语句时,SQL Server@@TRANCOUNT1;使用COMMIT TRANSACTIONCOMMIT WORK时,SQL Server@@TRANCOUNT递减1;而使用ROLLBACK TRANSACTION时(不包括使用ROLLBACK TRANSACTION savepoint_name的情况),所有的事务都被回滚,对应的,@@TRANCOUNT直接递减为0

嵌套事务一般出现在嵌套存储过程时,但一般不建议使用嵌套事务,这会增加事务控制的难度。一般建议的事务处理方法,是在可能出现嵌套事务的地方,通过判断@@TRANCOUNT的值来确定当前的事务数,如果当前没有事务,则开启新的事务;如果已经有事务,则使用SAVE TRANSACTION savepoint_name语句设置事务保存点,以便在需要回滚当前处理的时候,可以通过ROLLBACK TRANSACTION savepoint_name语句将事务回滚到保存点。

3         Template

下面是一个涉及TRY…CATCH和事务处理的模板。可以参考这个模板来编写业务存储过程,如果业务处理不涉及事务,则可以去掉事务处理的那些部分。

CREATE PROC procedure_name
AS
SET NOCOUNT ON
 
-- 当前的事务数
DECLARE
       @trancount int
SELECT
       @trancount = @@TRANCOUNT
 
-- TRY...CATCH 处理
BEGIN TRY
       -- ========================================
       -- 标准的事务处理模块块
       -- a. 开启事务, 或者设置事务保存点
       IF @trancount = 0
              BEGIN TRAN
       ELSE
              SAVE TRAN TRAN_SavePoint
 
       -- b. 这里放置处于事务中的各种处理语句
 
       -- c. 提交事务
       --    有可提交的事务, 并且事务是在当前模块中开启的情况下, 才提交事务
       IF XACT_STATE() = 1 AND @trancount = 0
              COMMIT
       -- ========================================
 
      
 
       -- ========================================
       -- 为了防止TRY 中有遗漏的事务处理, 可以在TRY 模拟的结束部分做最终的判断
       IF @trancount = 0
       BEGIN
              IF XACT_STATE() = -1
                     ROLLBACK TRAN
              ELSE
              BEGIN        
                     WHILE @@TRANCOUNT > 0
                           COMMIT TRAN
              END
       END
END TRY
BEGIN CATCH
       -- ========================================
       -- 在CATCH 模块, 应该首先处理事务
       IF XACT_STATE() <> 0
       BEGIN
              IF @trancount = 0
                     ROLLBACK TRAN
 -- XACT_STATE 为-1 时, 不能回滚到事务保存点, 这种情况留给外层调用者做统一的事务回滚
-- 通过@@TRANCOUNT > @trancount 的判断, 即使在TRY 模块中没有设置事务保存点的情况下跳到此步骤, 也不会出错
              ELSE IF XACT_STATE() = 1 AND @@TRANCOUNT > @trancount
                     ROLLBACK TRAN TRAN_SavePoint
       END
 
       -- ========================================
       -- 错误消息处理
       -- a. 获取错误信息
       -- 这提提取了错误相关的全部信息, 可以根据实际需要调整
       DECLARE
              @error_number int,
              @error_message nvarchar(2048),
              @error_severity int,
              @error_state int,
              @error_line int,
              @error_procedure nvarchar(126),
              @user_name nvarchar(128),
              @host_name nvarchar(128)
 
       SELECT
              @error_number = ERROR_NUMBER(),
              @error_message = ERROR_MESSAGE(),
              @error_severity = ERROR_SEVERITY(),
              @error_state = ERROR_STATE(),
              @error_line = ERROR_LINE(),
              @error_procedure = ERROR_PROCEDURE(),
              @user_name = SUSER_SNAME(),
              @host_name = HOST_NAME()
 
       -- b. 对于重要的业务处理存储过程, 应该考虑把错误记录到表中备查(这个表需要先建立)
       --    记录错误应该在没有事务的情况下进行了, 否则可能因为外层事务的影响导致保存失败
       IF XACT_STATE() = 0  
              INSERT dbo.tb_ErrorLog(
                     error_number,
                     error_message,
                     error_severity,
                     error_state,
                     error_line,
                     error_procedure,
                     user_name,
                     host_name,
                     indate)
              VALUES(
                     @error_number,
                     @error_message,
                     @error_severity,
                     @error_state,
                     @error_line,
                     @error_procedure,
                     @user_name,
                     @host_name,
                     GETDATE())
 
 -- c. 如果没有打算在CATCH 模块中对错误进行处理, 则应该抛出错误给调用者
 -- 注: 不允许在被SSB 调用的存储过程中, 将错误或者其他信息抛出
 -- 因为SSB 是自动工作的, 如果它调用的存储过程有抛出信息, 则这个信息会被直接记录到SQL Server 系统日志
  -- 而目前SSB 的消息数量是很多的, 这会导致SQL Server 日志爆涨掉
 -- 对于被SSB 调用的存储过程, 应该在CATCH 模块中加入自己的错误处理(最简单的就是将错误记录到表中)
       RAISERROR(
       N'User: %s, Host: %s, Procedure: %s, Error %d, Level %d, State %d, Line %d, Message: %s ',
              @error_severity,
              1,
              @user_name,
              @host_name,
              @error_procedure,
              @error_number,
              @error_severity,
              @error_state,
              @error_line,
              @error_message)
END CATCH
GO

4         Policy or suggest

在使用TRY…CATCH和事务处理时,我们有如下的一些规范需要遵守:

n   禁止在发布到production的存储过程中抛出警告或信息性消息,这包含使用PRINT语句和使用RAISERROR语句触发严重性为10或更低的错误

n   使用TRY…CATCH时,CATCH块中必须进行错误处理

n   对于重要的业务存储过程,必须建立对应的错误日志记录表,将CATCH块捕获的错误记录到错误日志记录表中

n   对于被DBASSB存储过程自动调用的存储过程,禁止抛出任何信息,所有的错误应该在被调用的存储过程中完成。虽然被调用的存储过程发生错误可以被DBASSB存储过程捕获,但由于涉及业务处理,DBA无法修复这些错误,故这些错误不应该给出DBA。而对于抛出的信息,这个不会被捕获,但由于是SSB自动调用的,因此会写入SQL Server的日志中,这可能会产生大量的日志,导致磁盘空间紧张,从而影响SQL Server运行

n   在嵌套调用的存储过程的时候,建议对存储过程的返回值做判断,以确定被调用的存储过程是否出现过问题。要获取存储过程的返回值,可以使用类似下面的调用方法(除非使用RETURN 语句手工设置返回值,否则无论被调用的存储过程中产生的错误是否被处理,只要有错误产生,返回的值都不会是0

DECLARE
   @sp_re int
 
EXEC @sp_re = dbo.procedure_name
 
IF @sp_re <> 0
   RAISERROR('has some error', 16, 1)

 以上就是sql 2005 try catch 的详细介绍的内容,更多相关内容请关注php中文网(www.php.cn)!

华友商贸仿阿里巴巴B2B电子商务系统
华友商贸仿阿里巴巴B2B电子商务系统

采用C#.NET,多层架构开发,后台采用大型MS SQL SERVER 数据库和存储过程,速度、性能更胜一筹。 前台功能介绍: 1、网页首页显示有精品推荐,商业机会分类列表,最新供求信息,网站动态,最新企业等; 2、商业机会栏目功能有:二级分类,已经带有详细分类的数据库,后台可以更改增加操作; 3、展厅展品栏目功能:二级分类,已经带有详细分类的数据库,后台可以更改增加操作,栏目分为分类显示展示的产

下载

 

相关专题

更多
c++主流开发框架汇总
c++主流开发框架汇总

本专题整合了c++开发框架推荐,阅读专题下面的文章了解更多详细内容。

78

2026.01.09

c++框架学习教程汇总
c++框架学习教程汇总

本专题整合了c++框架学习教程汇总,阅读专题下面的文章了解更多详细内容。

45

2026.01.09

学python好用的网站推荐
学python好用的网站推荐

本专题整合了python学习教程汇总,阅读专题下面的文章了解更多详细内容。

118

2026.01.09

学python网站汇总
学python网站汇总

本专题整合了学python网站汇总,阅读专题下面的文章了解更多详细内容。

10

2026.01.09

python学习网站
python学习网站

本专题整合了python学习相关推荐汇总,阅读专题下面的文章了解更多详细内容。

14

2026.01.09

俄罗斯手机浏览器地址汇总
俄罗斯手机浏览器地址汇总

汇总俄罗斯Yandex手机浏览器官方网址入口,涵盖国际版与俄语版,适配移动端访问,一键直达搜索、地图、新闻等核心服务。

71

2026.01.09

漫蛙稳定版地址大全
漫蛙稳定版地址大全

漫蛙稳定版地址大全汇总最新可用入口,包含漫蛙manwa漫画防走失官网链接,确保用户随时畅读海量正版漫画资源,建议收藏备用,避免因域名变动无法访问。

348

2026.01.09

php学习网站大全
php学习网站大全

精选多个优质PHP入门学习网站,涵盖教程、实战与文档,适合零基础到进阶开发者,助你高效掌握PHP编程。

42

2026.01.09

php网站搭建教程大全
php网站搭建教程大全

本合集专为零基础用户打造,涵盖PHP网站搭建全流程,从环境配置到实战开发,免费、易懂、系统化,助你快速入门建站!

12

2026.01.09

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
SQL 教程
SQL 教程

共61课时 | 3.4万人学习

SQL优化与排查(MySQL版)
SQL优化与排查(MySQL版)

共26课时 | 2.3万人学习

MySQL索引优化解决方案
MySQL索引优化解决方案

共23课时 | 2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号