sql server 的 try...catch 无法捕获语法错误,因其仅处理运行时错误(如除零、约束冲突),而语法或对象不存在等编译期错误在存储过程创建时即报错,根本不会执行到 try 块中。

SQL Server 中 TRY...CATCH 为什么捕不到语法错误?
因为 TRY...CATCH 只捕获运行时错误(如除零、主键冲突),不捕获编译期错误(如表不存在、拼错关键字)。这类错误在存储过程创建时就报错,根本不会执行到 TRY 块里。
常见现象:CREATE PROCEDURE 执行失败,提示 Invalid object name 'xxx',但你在 TRY 里包了 SELECT * FROM xxx —— 没用,这步压根没机会运行。
- 真正能被
TRY...CATCH捕获的:INSERT违反约束、CONVERT类型转换失败、RAISERROR主动抛出的错误 - 检查语法/对象是否存在,得靠
IF OBJECT_ID('xxx') IS NOT NULL或动态 SQL +EXEC sp_executesql配合TRY...CATCH - SQL Server 2019+ 支持
THROW,比RAISERROR更准确保留原始错误号和状态,推荐替代
PostgreSQL 存储过程怎么写异常处理?
PostgreSQL 没有 TRY...CATCH,用 BEGIN ... EXCEPTION 块,且只支持在 PL/pgSQL 函数中使用,不能直接用于 DO 块或纯 SQL 存储过程。
关键限制:异常处理必须写在函数体内部,且每个 EXCEPTION 分支只能捕获一种 SQLSTATE 错误码,不能像 SQL Server 那样用通配符。
- 常用 SQLSTATE:
'23505'(唯一约束违规)、'23503'(外键违规)、'42703'(列不存在) - 别写
WHEN OTHERS THEN后直接RETURN—— 会吞掉关键上下文,至少记录GET STACKED DIAGNOSTICS获取错误位置 - 注意:在
INSERT ... ON CONFLICT场景下,优先用原生冲突处理,而不是靠异常捕获,性能差一个数量级
MySQL 存储过程中 DECLARE HANDLER 的坑
MySQL 的异常处理依赖 DECLARE HANDLER,但它对错误类型的识别很粗糙 —— 比如 SQLSTATE 'HY000' 是通用码,可能覆盖了本该重试的锁等待(1205 死锁)和该拒绝的权限错误(1045)。
本书将PHP开发与MySQL应用相结合,分别对PHP和MySQL做了深入浅出的分析,不仅介绍PHP和MySQL的一般概念,而且对PHP和MySQL的Web应用做了较全面的阐述,并包括几个经典且实用的例子。 本书是第4版,经过了全面的更新、重写和扩展,包括PHP5.3最新改进的特性(例如,更好的错误和异常处理),MySQL的存储过程和存储引擎,Ajax技术与Web2.0以及Web应用需要注意的安全
更麻烦的是:Handler 一旦触发,后续语句默认继续执行,不像 SQL Server 那样自动退出 TRY 块。容易造成“错误已发生,但逻辑还在往下跑”的诡异行为。
- 必须显式加
LEAVE或ITERATE控制流程,否则 handler 执行完就接着跑下一行 - 不要用
DECLARE CONTINUE HANDLER处理严重错误;改用DECLARE EXIT HANDLER确保及时退出 -
SQLSTATE和 MySQL 错误号(如1062)可以混用,但优先用SQLSTATE,兼容性更好
跨数据库统一异常日志怎么落地?
没有银弹。各数据库的错误结构、可读字段、上下文信息差异太大,硬套一个“通用日志表”反而让排查更慢。
实际建议是分层记录:数据库层只记最小必要字段(错误号、SQLSTATE、发生时间、语句前 100 字符),应用层再补全调用栈、参数、用户 ID 等上下文。
- SQL Server:从
ERROR_NUMBER()、ERROR_MESSAGE()、ERROR_LINE()取值,别依赖ERROR_PROCEDURE()—— 动态 SQL 里它常为空 - PostgreSQL:用
SQLERRM和PG_CONTEXT,但注意PG_CONTEXT在嵌套函数里可能截断 - MySQL:
GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE是唯一可靠方式,@@error_count不够细
最易被忽略的一点:所有数据库里,事务中的异常处理都默认不自动回滚——你得自己写 ROLLBACK 或设 SET XACT_ABORT ON(SQL Server)/ ON ERROR ROLLBACK(PostgreSQL 的 plpgsql 函数内)。









