当前位置: 首页
数据库
SQL Server 2005 中使用 Try Catch 处理异常

SQL Server 2005 中使用 Try Catch 处理异常

热心网友 时间:2026-04-30
转载

TRY...CATCH:SQL Server异常处理的优雅进化

如果你是SQL Server的老用户,一定对2005和2008版本引入的TRY...CATCH功能记忆犹新。它彻底改变了我们处理数据库错误的方式,把开发人员从繁琐的全局变量检查中解放了出来,让异常处理变得清晰、直观。今天,我们就来好好聊聊这个功能,看看它如何让我们的代码更加健壮。

一、回顾:SQL Server 2000时代的异常处理

在TRY...CATCH出现之前,SQL Server 2000的世界里,错误处理是件挺“手工”的活儿。开发人员必须紧盯着那个全局变量@@ERROR,在每一条可能出错的DML语句(比如UPDATE、INSERT)之后,立刻检查它。你猜怎么着?因为这个变量会被紧接着的下一个数据库操作重置,所以检查动作必须争分夺秒,绝不能延迟。

看看下面这个典型的存储过程例子,你就能感受到那种“步步惊心”的编码风格:

CREATE PROC usp_AccountTransaction
    @AccountNum INT,
    @Amount DECIMAL
AS
BEGIN
    BEGIN TRANSACTION --开始一个事务
      UPDATE MyChecking SET Amount = Amount - @Amount
        WHERE AccountNum = @AccountNum
      IF @@ERROR != 0 --在每个DML语句后立即检查@@ERROR
      BEGIN
        ROLLBACK TRANSACTION --如果出错,回滚事务
        RETURN
      END
      ELSE
      BEGIN
        UPDATE MySa vings SET Amount = Amount + @Amount
          WHERE AccountNum = @AccountNum
        IF @@ERROR != 0 --再次检查@@ERROR
        BEGIN
          ROLLBACK TRANSACTION --如果出错,回滚事务
          RETURN
        END
        ELSE
        BEGIN
          COMMIT TRANSACTION --全部成功,最终提交事务
          RETURN
        END
      END
END
GO

这种方式的问题显而易见:代码被大量重复的错误检查逻辑所淹没,业务逻辑本身反而显得支离破碎。维护起来,着实需要点耐心。

二、进化:SQL Server 2005引入的TRY...CATCH

SQL Server 2005带来的TRY...CATCH,就像是给T-SQL语言注入了一股现代编程的清风。它的语法对于任何熟悉C#或Ja va的开发者来说都倍感亲切,这种跨语言的一致性,本身就是一次巨大的体验提升。当然了,如果你怀念旧方式,@@ERROR依然被支持。

1. 核心语法结构

它的结构非常清晰,一看就懂:

BEGIN TRY
    -- 可能抛出异常的代码块
    Try Statement 1
    Try Statement 2
    ...
END TRY
BEGIN CATCH
    -- 异常处理代码块
    Catch Statement 1
    Catch Statement 2
    ...
END CATCH

当TRY块中的任何语句发生错误时,控制流会立即跳转到CATCH块,剩下的TRY块代码将被跳过。这就像为你的代码逻辑安装了一个安全网。

2. 强大的错误信息函数

进入CATCH块后,你就可以调用一系列专属的系统函数来“诊断”刚才发生的错误,这比昔日的@@ERROR那一丁点信息强太多了:

ERROR_NUMBER() – 返回错误号。
ERROR_SEVERITY() – 返回错误严重级别。
ERROR_STATE() – 返回错误状态号。
ERROR_PROCEDURE() – 返回出错的存储过程名。
ERROR_LINE() – 返回发生错误的具体行号。
ERROR_MESSAGE() – 返回完整的错误消息文本。

来个小例子感受一下:

BEGIN TRY
    SELECT GETDATE()
    SELECT 1/0 --经典的除零错误!
END TRY
BEGIN CATCH
    SELECT 'There was an error! ' + ERROR_MESSAGE()
    RETURN
END CATCH;

3. 事务处理的优雅写法

有了TRY...CATCH,处理事务中的错误就变得异常优雅。看,之前那个冗长的存储过程,现在可以写得如此简洁:

ALTER PROC usp_AccountTransaction
    @AccountNum INT,
    @Amount DECIMAL
AS
BEGIN
    BEGIN TRY -- 开启Try块
      BEGIN TRANSACTION -- 开始事务
        UPDATE MyChecking SET Amount = Amount - @Amount
          WHERE AccountNum = @AccountNum
        UPDATE MySa vings SET Amount = Amount + @Amount
          WHERE AccountNum = @AccountNum
      COMMIT TRAN -- 一切顺利,提交事务!
    END TRY
    BEGIN CATCH
      IF @@TRANCOUNT > 0
        ROLLBACK TRAN -- 捕获到异常,回滚事务
      -- 你还可以用RAISEERROR()将异常再次抛出,通知调用者
      RAISERROR(ERROR_MESSAGE(), ERROR_SEVERITY(), 1)
    END CATCH
END
GO

代码的逻辑主干一下子清晰了:TRY块里专注业务,CATCH块里统一收拾残局。这才是现代化错误处理该有的样子。

三、实战:构建一个完整的错误日志系统

理论说得再好,不如动手实践。我们来看一个更实际的场景:如何利用TRY...CATCH构建一个错误日志记录系统。

首先,创建一张表来存放错误日志:

CREATE TABLE ErrorLog(errNum INT,ErrSev NVARCHAR(1000),ErrState INT,ErrProc NVARCHAR(1000),ErrLine INT, ErrMsg NVARCHAR(2000))

接着,创建一个存储过程来自动化日志记录工作。这个过程会在被调用时,捕获当前错误上下文并存入日志表:

CREATE PROCEDURE ErrorLog
AS
    SELECT ERROR_NUMBER() AS ErrNum,ERROR_SEVERITY()AS ErrSev,ERROR_STATE() AS ErrState,ERROR_PROCEDURE() AS ErrProc,ERROR_LINE()AS ErrLine,ERROR_MESSAGE()AS ErrMsg
    INSERT
    INTO ErrorLog
    VALUES(ERROR_NUMBER(),ERROR_SEVERITY(),ERROR_STATE(),ERROR_PROCEDURE(),ERROR_LINE(),ERROR_MESSAGE())
GO

现在,我们编写一个业务存储过程,并在其中使用TRY...CATCH和这个日志工具:

USE [Your_Test]
GO
ALTER PROCEDURE [dbo].[getTodayBirthday]
AS
BEGIN TRY
    declare @today datetime;
    SET @today = GETDATE(); -- 获取今天日期
    DECLARE @day VARCHAR(2);
    SET @day =REPLACE(DAY(@today),0,'');
    DECLARE @month VARCHAR(2) ;
    SET @month = REPLACE(month(@today),0,'');
    DECLARE @year VARCHAR(4);
    SET @year = YEAR(@today);

    SELECT * FROM dbo.UserInfo
    WHERE REPLACE(DAY(CONVERT(DATETIME,Birthday )),0,'') =@day
      AND REPLACE(MONTH(CONVERT(DATETIME,Brithday)),0,'')=@month
      AND Birthday IS NOT NULL
END TRY
BEGIN CATCH
    EXEC ErrorLog -- 一旦出错,立即调用日志过程保存证据
END CATCH

需要特别注意的是,ERROR_NUMBER(), ERROR_SEVERITY() 等这一系列错误函数,只能在CATCH块的作用域内使用。在TRY块或CATCH块之外调用它们,是获取不到值的。

总的来说,从@@ERROR到TRY...CATCH,SQL Server的异常处理完成了一次漂亮的升级。它不仅让代码更易写、易读,更重要的是,它为构建健壮、可维护的数据库应用提供了坚实的基础设施。如果你的系统还没用上这个特性,现在是时候尝试一下了。

来源:https://www.jb51.net/article/83379.htm

游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

同类文章
更多
Redis 7.0增量AOF重写RDB前导码配置详解

Redis 7.0增量AOF重写RDB前导码配置详解

先说一个几乎所有人都踩过的典型误区:很多人把 aof-use-rdb-preamble yes 当作开启“增量重写”的开关。实际上,这个配置只干了一件事——让重写后的 AOF 文件头部带上 RDB 快照。它解决的是加载速度问题,跟“增量重写”本身的概念压根不是一回事。真正的增量重写,依赖的是 Red

时间:2026-07-02 09:05
在Python Tornado异步框架中安全执行SQL命令的方法与最佳实践

在Python Tornado异步框架中安全执行SQL命令的方法与最佳实践

直接在Tornado里用SQLAlchemy同步执行SQL,结果就是阻塞IOLoop,所谓“异步框架里写同步数据库代码”,等于白搭。安全执行的关键不是“怎么写SQL”,而是“怎么不卡住事件循环”。 为什么不能在RequestHandler里直接调用session execute() 因为sessio

时间:2026-07-02 09:04
利用SQL触发器实现在INSERT数据时自动同步到审计表

利用SQL触发器实现在INSERT数据时自动同步到审计表

先说结论:可以用触发器把 INSERT 数据同步到审计表,但必须用 AFTER INSERT,并且审计表的字段顺序、类型、字符集得和源表严格一致。否则,轻则写入错位、数据截断,重则直接报错、丢数据。下面把这些坑一个一个掰开说。 能,但必须用 AFTER INSERT,且审计表字段顺序、类型、字符集要

时间:2026-07-02 09:04
如何用SQL编写按不同工作日统计员工出勤率

如何用SQL编写按不同工作日统计员工出勤率

在实际业务中,统计不同工作日的出勤率是HR系统里的高频需求。如果直接按日期函数分组,很容易掉进语言环境、索引失效或分母口径的坑里。下面就来拆解具体的实现要点。 必须用 CASE WHEN 将日期映射为固定 weekday 标签(如 Mon )再分组,避免语言环境导致的分组断裂;需过滤 DOW IN

时间:2026-07-02 09:03
Spring Boot 3动态拼接SQL为何引发严重安全漏洞

Spring Boot 3动态拼接SQL为何引发严重安全漏洞

SQL注入漏洞的核心成因,本质上是因为用户输入直接参与了SQL语句的字符串拼接,而未采用参数化绑定机制。在MyBatis中使用${}、QueryWrapper中调用apply()与last()、JPA的@Query注解进行拼接等操作,都会绕过PreparedStatement的安全防护。动态字段必须

时间:2026-07-02 09:03
热门专题
更多
刀塔传奇破解版无限钻石下载大全 刀塔传奇破解版无限钻石下载大全
洛克王国正式正版手游下载安装大全 洛克王国正式正版手游下载安装大全
思美人手游下载专区 思美人手游下载专区
好玩的阿拉德之怒游戏下载合集 好玩的阿拉德之怒游戏下载合集
不思议迷宫手游下载合集 不思议迷宫手游下载合集
百宝袋汉化组游戏最新合集 百宝袋汉化组游戏最新合集
jsk游戏合集30款游戏大全 jsk游戏合集30款游戏大全
宾果消消消原版下载大全 宾果消消消原版下载大全
  • 日榜
  • 周榜
  • 月榜