SQL存储过程中使用TRY...CATCH块的技巧有哪些?

梦晨君_4258

梦晨君_4258

2026-07-04

521人浏览

原创

try...catch仅捕获严重级别11–19的运行时错误,编译期错误(如表不存在、语法错误、变量赋值失败)在try执行前即终止批处理;raiserror级别

sql存储过程中使用try...catch块的技巧有哪些?

TRY...CATCH 为什么有些错误根本进不去 CATCH?

因为 TRY...CATCH 只捕获严重级别 11–19 的运行时错误,编译期错误(比如 SELECT * FROM NonExistentTable、语法写错、变量类型赋值失败)压根不会执行到 TRY 块里,直接报错退出批处理。

常见“假失效”场景:

  • RAISERROR('msg', 10, 1) 不会触发 CATCH —— 严重级必须 ≥11 才行
  • DECLARE @x INT = 'abc' 在编译阶段就失败,TRY 还没开始
  • 动态 SQL(如 EXEC('SELECT * FROM ...'))能把部分编译期错误转为运行时报错,从而被 CATCH 捕获
  • DDL 语句(CREATE TABLE)出错可能直接中断批处理,CATCH 来不及响应

ERROR_*() 函数必须在 CATCH 第一行就调用

所有 ERROR_NUMBER()ERROR_MESSAGE()ERROR_LINE() 等函数只在当前 CATCH 块内有效,且只返回最近一次错误信息。一旦你在 CATCH 里执行了其他可能出错的操作(比如往日志表 INSERT),原始错误上下文就会被覆盖。

正确做法是立即存入变量:

DECLARE @ErrorNumber INT = ERROR_NUMBER();
DECLARE @ErrorMessage NVARCHAR(4000) = ERROR_MESSAGE();
DECLARE @ErrorLine INT = ERROR_LINE();
DECLARE @ErrorProcedure SYSNAME = ERROR_PROCEDURE();

注意:ERROR_MESSAGE() 里可能含单引号,拼接进 INSERT 语句前建议用 REPLACE(@ErrorMessage, '''', '''''') 防截断。

事务回滚不能靠“进了 CATCH 就自动 rollback”

默认情况下,约束冲突这类错误不会自动回滚事务——事务仍处于打开状态,但可能已标记为不可提交(XACT_STATE() = -1)。此时盲目 ROLLBACK TRANSACTION 可能失败,而只查 @@TRANCOUNT 也不可靠(它可能 > 0 但事务实际已失效)。

清程爱画
清程爱画

一款AI视频创作工具,主要用于AI图像与视频生成平台,拥有超丰富的工作流社区和多种图像生成模式,适合需要提升相关任务效率的用户。

下载

安全写法是先判断事务状态:

IF XACT_STATE()  0
    ROLLBACK TRANSACTION;

更关键的是:务必在 TRY 块开头加 SET XACT_ABORT ON,否则多数错误不会终止当前批处理,CATCH 可能被绕过;但注意,SET XACT_ABORT ON 本身会让某些错误跳过 CATCH 直接退出——所以它和 TRY...CATCH 是互斥增强关系,不是简单开关。

重抛错误该用 THROW 还是 RAISERROR?

SQL Server 2012+ 强烈推荐用 THROW,而不是 RAISERROR

THROW(无参数)能原样保留原始错误号、消息、行号和状态;而 RAISERROR 必须手动传参,且强制把错误号改成 50000,丢失关键定位信息。

示例:

BEGIN CATCH
    -- 先保存上下文
    DECLARE @ErrorNumber INT = ERROR_NUMBER();
    DECLARE @ErrorMessage NVARCHAR(4000) = ERROR_MESSAGE();
    -- ……记录日志逻辑……
    THROW; -- 原样抛给上层,不丢上下文
END CATCH

如果要在日志里记录后再向上抛,别用 RAISERROR(@ErrorMessage, @ErrorSeverity, @ErrorState) —— 它改写了错误号,调试时你会找不到原始错误来源。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

2023.10.12

3703

8

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.27

791

4

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

2024.02.23

949

5

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

5481

10

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

2483

4

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

2024.04.07

5460

11

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

2024.04.29

7101

6

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

970

5

sql中删除一列的命令是什么
sql中删除一列的命令是什么

在sql中,使用alter table语句可以删除一列,语法为:alter table table_name drop column column_name。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

852

5

热门下载

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

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.6万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 133.1万人学习