Oracle PL/SQL插入值数量超表字段时异常处理不生效问题
你使用的articulo表结构如下:
SQL> describe articulo; CODIGO - NUMBER(5) NOMBRE - VARCHAR2(20) PRECIO - NUMBER(7,2) STOCK - NUMBER(3) MARCA - VARCHAR2(20) MODELO - VARCHAR2(20)
你测试时故意给插入语句传入7个值,预期触发值数量多于字段数的错误,并用存储过程的异常块捕获,但异常逻辑未生效,原存储过程代码如下:
create or replace procedure procedure_exep as begin insert into articulo values(11, 'mayonesa', 4.50, 50, 'Alacena', 'KDJF', 'Amarillo'); exception when others then dbms_output.put_line('Los valores ingresados son mayores a los campos de la tabla'); end; /
异常未触发的原因
这个错误根本没有走到运行阶段,自然不会被EXCEPTION块捕获。
你写的是静态INSERT语句,PL/SQL在编译存储过程的时候就会做语法校验:会直接检查INSERT INTO 表 VALUES后面的值的数量,和表的字段数量是否一致。你这里传7个值、表只有6个字段,编译阶段就直接抛出ORA-00913: 值过多的错误,你在编译完存储过程后执行show errors命令就能看到这个报错。此时整个存储过程会被标记为无效对象,根本不会执行存储过程里的任何逻辑,包括你写的异常捕获代码。
要明确:PL/SQL的异常处理机制只能捕获存储过程编译通过后,运行过程中产生的错误,编译期的语法、结构不匹配错误是无法被内部异常块捕获的。
正确修改方式
如果是正常业务开发,这个错误属于编码阶段的语法问题,直接把插入值的数量改成和字段数一致即可,不需要特意留到运行时捕获。
如果你确实要测试异常捕获逻辑、或者需要动态拼接SQL处理不确定数量的参数,需要把静态SQL改成动态SQL,把SQL校验的时机从编译期推迟到运行时,这样异常块就能正常抓到错误。修改后的代码如下:
create or replace procedure procedure_exep as begin -- 用EXECUTE IMMEDIATE执行动态SQL,编译阶段不会校验值和字段的匹配关系 execute immediate 'insert into articulo values(:1,:2,:3,:4,:5,:6,:7)' using 11, 'mayonesa', 4.50, 50, 'Alacena', 'KDJF', 'Amarillo'; exception when others then dbms_output.put_line('Los valores ingresados son mayores a los campos de la tabla'); -- 调试时可以放开下面这行,打印实际错误信息方便定位 -- dbms_output.put_line('错误详情:' || SQLERRM); end; /
修改后重新编译存储过程,再调用时就能正常触发异常分支,打印你预设的提示信息。
内容的提问来源于stack exchange,提问作者Andy Salim Rojas Hinojosa
相关产品推荐
相关产品推荐

