PL/SQL Developer中文网站 > 售前问题 > PL/SQL怎么设置异常处理 PL/SQL异常没有被捕获如何排查

PL/SQL怎么设置异常处理 PL/SQL异常没有被捕获如何排查

发布时间:2026-08-31 17: 29: 00

PL/SQL可以通过【EXCEPTION】区处理运行过程中出现的异常,包括Oracle预定义异常、没有预定义名称的内部异常以及用户自定义异常。常见的【NO_DATA_FOUND】【TOO_MANY_ROWS】【DUP_VAL_ON_INDEX】【ZERO_DIVIDE】可以直接捕获,自定义业务异常则需要声明并主动触发。出现程序已经编写异常处理但错误仍直接返回调用端时,应重点检查异常发生在哪个代码块、处理器捕获的异常名称是否一致,以及异常是否在声明区或异常处理区再次产生。

一、PL/SQL怎么设置异常处理

PL/SQL异常处理通常写在当前程序块的【EXCEPTION】区域,并按照具体异常优先、【WHEN OTHERS】兜底的方式组织。需要识别指定ORA错误时,可以通过【PRAGMA EXCEPTION_INIT】给错误码绑定名称。

1、处理Oracle预定义异常

①找到可能产生异常的【BEGIN】代码区域。

②在正常业务语句之后增加【EXCEPTION】。

③使用【WHEN NO_DATA_FOUND THEN】处理查询不到数据的情况。

④可能返回多条记录时增加【WHEN TOO_MANY_ROWS THEN】。

⑤唯一约束冲突可以使用【WHEN DUP_VAL_ON_INDEX THEN】。

⑥除零问题可以使用【WHEN ZERO_DIVIDE THEN】。

⑦在各处理分支中记录错误、回滚事务或返回业务状态。

⑧最后根据业务要求决定是否继续向上抛出异常。

预定义异常已经在PL/SQL的【STANDARD】包中声明,不需要再次自行定义。如果重新声明同名异常,局部名称会覆盖原来的预定义名称,反而可能导致对应处理器无法捕获实际Oracle异常。

2、处理指定ORA错误

有些数据库错误拥有错误码,但没有可直接使用的预定义异常名称,这时可以自行建立异常名称。

①在过程、函数或匿名块的声明部分定义异常,例如【deadlock_detected EXCEPTION】。

②紧接着使用【PRAGMA EXCEPTION_INIT】。

③把异常名称与对应Oracle错误码绑定,例如死锁错误使用【-60】。

④在【EXCEPTION】区域增加【WHEN deadlock_detected THEN】。

⑤在处理分支记录当前事务信息。

⑥根据业务要求执行【ROLLBACK】或其他恢复处理。

⑦需要让上层继续感知异常时执行【RAISE】。

【EXCEPTION_INIT】中的Oracle错误码通常使用负数形式,配置前应先确认实际ORA编号,不能根据错误文字猜测。

3、设置用户自定义异常

①在声明区域定义【业务异常名EXCEPTION】。

②在业务判断中检查需要拦截的条件。

③条件成立时执行【RAISE业务异常名】。

④在当前代码块的【EXCEPTION】区域增加对应【WHEN】分支。

⑤需要向调用程序返回自定义错误码时,可以使用【RAISE_APPLICATION_ERROR】。

⑥自定义错误码使用Oracle规定的【-20000】到【-20999】范围。

⑦在错误信息中写明具体业务原因。

这种方式适合库存不足、参数范围错误、业务状态不允许修改等数据库自身不会自动产生ORA异常的情况。

二、PL/SQL异常没有被捕获如何排查

异常没有进入预期的【WHEN】分支时,首先要确认异常究竟发生在哪个PL/SQL块。异常处理存在明确作用域,某个内层Block捕获不到的异常会向外传播,但并不是任何外层代码都能继续使用原来的异常名称。

1、检查异常发生的代码块层级

①找到实际抛出错误的语句。

②确认该语句位于哪个【BEGIN】和【END】之间。

③检查这个Block是否存在【EXCEPTION】区域。

④确认对应【WHEN】分支属于同一个Block或它的外层Block。

⑤内层Block没有对应处理器时,异常会继续向外传播。

⑥逐层检查外层过程、函数和匿名块。

⑦如果一直没有匹配处理器,异常最终会返回调用端。

处理器不是按照源文件中的距离匹配,而是按照PL/SQL块的嵌套关系查找,所以异常代码和【WHEN】看起来位置接近,也不代表它们处于同一个作用域。

2、检查异常是不是发生在声明区域

这一类情况很容易被误判为“EXCEPTION没有执行”。

①检查【DECLARE】或过程声明区中的变量初始化。

②查看类型转换、函数调用和常量赋值是否可能报错。

③如果异常在当前Block的声明区域产生,不会进入这个Block自己的异常处理器。

④在外层再增加一个PL/SQL Block。

⑤由外层【EXCEPTION】处理声明阶段产生的异常。

⑥重新执行并观察捕获位置。

例如变量精度过小导致初始化阶段产生【VALUE_ERROR】,当前块后面的EXCEPTION无法处理,只能继续向外围传播。

3、检查异常是否在处理器中再次被抛出

①进入实际执行到的【WHEN】分支。

②检查其中是否调用了其他过程或SQL。

③确认这些语句有没有产生新的异常。

④查看是否存在【RAISE】。

⑤检查是否调用了【RAISE_APPLICATION_ERROR】。

⑥如果处理器内部再次产生异常,新异常会直接向外层传播。

⑦在更外层Block增加对应处理逻辑进行验证。

因此看到调用端收到异常,并不一定表示最里面的处理器从未运行,也可能是处理完成后主动重新抛出了错误。

三、异常仍然无法定位时怎么继续检查

代码块和异常类型确认无误后,可以直接记录Oracle返回的错误码、错误栈和异常产生行号,再根据实际错误决定应该增加哪个处理器。

1、记录SQLCODE和SQLERRM

①在【WHEN OTHERS THEN】中获取【SQLCODE】。

②同时获取【SQLERRM】。

③把错误码和错误信息写入日志表或调试输出。

④重新触发一次异常。

⑤确认实际ORA错误是否和原来预计的一致。

⑥再决定是否改用具体异常处理器。

【WHEN OTHERS】适合兜底和定位未知错误,但不建议捕获以后什么都不做,否则上层程序可能误认为执行成功。

2、查看异常真正产生的位置

①在异常处理区获取【DBMS_UTILITY.FORMAT_ERROR_BACKTRACE】。

②同时记录【DBMS_UTILITY.FORMAT_ERROR_STACK】。

③查看错误最初发生的过程和代码行。

④沿调用栈检查对应存储过程、函数或触发器。

⑤找到真正产生异常的SQL或PL/SQL语句。

⑥修正后重新执行。

【FORMAT_ERROR_BACKTRACE】能够保留异常最初产生的位置,比只看最外层返回的错误行更适合排查多层过程调用。

3、检查自定义异常作用域

①找到自定义异常的声明位置。

②确认外层处理器是否能够访问该异常名称。

③如果异常只在内层Block声明,传播到外层后原名称已经超出作用域。

④需要外层按名称捕获时,把异常声明提升到外层或Package范围。

⑤无法调整声明范围时,在外层使用【WHEN OTHERS】并结合错误码判断。

⑥重新测试异常传播过程。

总结

PL/SQL设置异常处理时,可以使用预定义异常直接处理常见Oracle错误,通过EXCEPTION_INIT绑定指定错误码,也可以声明用户异常并通过RAISE主动触发。异常没有被捕获时,应优先检查代码块作用域、声明区域异常和异常处理器中的二次抛出,再利用SQLCODE、SQLERRM和错误回溯确定真正的异常位置。把异常发生位置和处理器所属Block对应起来,比单纯增加WHEN OTHERS更容易找到问题。如需进一步了解PL/SQL异常处理、异常传播与错误定位方法,欢迎联系咨询。

展开阅读全文

标签:plsql使用plsql使用教程plsql编码

PL/SQL Developer
专为Oracle数据库开发
咨询购买
最新文章
PL/SQL怎么设置异常处理 PL/SQL异常没有被捕获如何排查
PL/SQL可以通过【EXCEPTION】区处理运行过程中出现的异常,包括Oracle预定义异常、没有预定义名称的内部异常以及用户自定义异常。常见的【NO_DATA_FOUND】【TOO_MANY_ROWS】【DUP_VAL_ON_INDEX】【ZERO_DIVIDE】可以直接捕获,自定义业务异常则需要声明并主动触发。出现程序已经编写异常处理但错误仍直接返回调用端时,应重点检查异常发生在哪个代码块、处理器捕获的异常名称是否一致,以及异常是否在声明区或异常处理区再次产生。
2026-08-31
PL/SQL包怎么创建 PL/SQL包体编译后显示无效怎么办
PL/SQL包可以把相关过程、函数、变量和类型放在一起管理。创建时通常分成包规范和包体两部分。包体编译后显示【INVALID】,先别反复点编译,直接查看具体报错行会更快。
2026-07-30
PL/SQL游标怎么使用 PL/SQL游标循环性能差怎么优化
很多Oracle开发在写存储过程或批处理脚本时,都会碰到PL/SQL游标怎么使用,以及游标循环性能差怎么优化的问题。游标的作用是把查询到的数据逐行取出来处理,适合需要按记录去判断、计算或调用其他过程的场景,但游标不是越多越好,如果一条SQL就能完成的事却被写成一行一行循环处理,性能就很容易变差,写PL/SQL游标时,操作者要先判断是否真的需要游标,再去考虑循环写法、提交策略和批量处理方式。
2026-06-30
PL/SQL触发器怎么编写 PL/SQL触发器递归触发怎么排查
PL/SQL触发器的编写,和触发器递归触发的排查,这两件事情的关键,是需要先弄清楚触发器到底是在什么时候执行、针对哪一张表来执行、它是执行一次,还是每一行都会执行一次。在Oracle当中,trigger是存储在数据库里面的一种PL/SQL单元,它会在被指定的数据库事件发生的时候,自动地被触发并执行。触发器如果写得好,可以用它来做审计、补充一些字段,或者是进行数据的校验;可要是写得太重了,就容易带来递归触发、性能下降,还有维护起来比较困难这一类的问题。
2026-06-30
PL/SQL Developer怎么调试存储过程 PL/SQL Developer断点不生效怎么排查
一个存储过程能够成功地跑完,并不等于调试器就一定能在预先放好的断点那里停下来。要用PL/SQL Developer把存储过程的调试跑起来,得先满足几个条件才行:登录数据库的那个账号要有调试用的权限,打算调试的目标对象里面要带有调试的时候需要用到的信息,从Test Window里调用的得是当前最新版本的代码,而且断点的位置还要刚好落在那条真的会被执行到的语句上面,这几个条件缺哪一个都可能让断点停不下来。碰到断点没反应的情况,不建议反复去点运行按钮,与其一遍遍地重试,不如按一个固定的顺序逐项排查,更容易找到真正的原因。
2026-06-30
PL/SQL Developer怎么连接Oracle数据库 PL/SQL Developer连接信息怎么保存
数据库环境刚刚搭建起来的时候,最容易让人卡住的往往不是去写那些SQL语句,而是客户端软件、服务名和账号信息之间没有对齐。要想搞清楚PL/SQL Developer这个工具怎么去连接Oracle数据库,以及连接信息又该怎么保存,首先得确认本地的Oracle客户端和网络配置是可用的,然后再把那些经常用到的连接整理到它的连接列表里面去。在保存连接信息的时候,还要顺便区分一下是只保存账号名称,还是把密码也一起存进去,这一点对于办公用的个人电脑和那种多人共用的电脑来说,处理的方式可不能是一样的。
2026-06-30

咨询热线 400-8765-888