PL/SQL value_error 异常没有被捕获

Posted

技术标签:

【中文标题】PL/SQL value_error 异常没有被捕获【英文标题】:PL/SQL value_error exception not getting caught 【发布时间】:2018-01-18 05:22:58 【问题描述】:

这是我的部门表:

create table Department(
    DeptNo int primary key, 
    DeptName varchar2(21) not null, 
    DeptLocation varchar2(13) not null
);

我正在尝试为 DeptName 列插入长度超过接受的值,即 21,这意味着我应该得到“VALUE_ERROR”异常。 我正在运行的plsql代码是:

begin
    insert into department values(1, 'Some random department name', 'SomeLocation');
exception
    when value_error then
        dbms_output.put_line('Cannot store the value!');
end;

当我试图捕获异常时,它没有被捕获。我收到错误消息:

ORA-12899:列“SQL_ZIRHWMLFPCEAKPGYGJJZLSIFI”.“DEPARTMENT”.“DEPTNAME”的值太大(实际:27,最大值:21)ORA-06512:在第 2 行 ORA-06512:在“SYS.DBMS_SQL”,第 1721 行

但如果我将异常从“value_error”更改为“others”

begin
    insert into department values(1, 'Some random department name', 'SomeLocation');
exception
    when others then
        dbms_output.put_line('Cannot store the value!');
end;

然后我得到预期的输出

无法存储值!

我哪里做错了?请告诉我。谢谢!

PS:我在 livesql.oracle.com 上运行所有代码

【问题讨论】:

如果您对某个问题投反对票,请留言说明您这样做的原因。 【参考方案1】:

理想情况下,您使用的是正确的,它应该可以按预期工作。但是 VALUE_ERROR 异常在某些情况下表现不同。请参见下面的说明性示例。

根据文档 value_error 出现时有 发生算术、转换、截断或大小约束错误。 例如,当您的程序将列值选择为字符时 变量,如果值长于声明的长度 变量,PL/SQL 中止赋值并引发 VALUE_ERROR。在 程序语句,如果转换 字符串转换为数字失败。

最后一行说,在程序语句中,如果将字符串转换为数字失败,则会引发 VALUE_ERROR。,但是当我在块中运行它时会引发 INVALID_NUMBER 异常。 p>

SQL> declare
  2    n number;
  3  begin
  4    select to_number('a')
  5      into n
  6      from dual
  7    ;
  8  exception
  9    when value_error
 10    then
 11      dbms_output.put_line ('Value Error');
 12    when invalid_number
 13    then
 14      dbms_output.put_line ('Invalid Number');
 15  end;
 16  /
Invalid Number

PL/SQL procedure successfully completed.

我预计它会引发 VALUE_ERROR,但事实并非如此。因此,在您的情况下,Oracle 可能无法引发 value_error 并且当您使用 WHEN OTHERS 时,它可能会被捕获。

编辑:

好的。那么是否有可能通过给出以某种方式捕获 value_error 异常 值比变量声明的长度长?

显式引发系统异常:不是很优雅,但您可以按以下方式进行。

declare

var int;
var1 varchar2(21);
var2 varchar2(13);

begin

var1:='Some random department name';
var2:= 'SomeLocation'

If var1 > 21 then
 RAISE VALUE_ERROR; 
END IF; 

If var2 > 13 then
 RAISE VALUE_ERROR; 
END IF; 

insert into department values(1, var1, var2);

exception
    when value_error  then
        dbms_output.put_line('Cannot store the value!');
end;

【讨论】:

好的。那么是否有可能通过赋予值长于变量声明的长度来捕获 value_error 异常? 您可以使用 length 来检查变量长度,如果它超过指定的限制,则引发 VALUE_ERROR。 我在您答案的编辑部分尝试了代码。 var1:='Some random department name'; 行本身会引发 value_error,这意味着我什至不必检查 var1 > 21。所以这行得通!谢谢。 +1 建议【参考方案2】:

VALUE_ERROR 不是您运行代码时引发的异常,如果需要,您可以定义一个 EXCEPTION 并捕获它,请参见下面的代码示例,

DECLARE
   ORA_12899 EXCEPTION;
   PRAGMA EXCEPTION_INIT(ORA_12899, -12899);
begin
    insert into department values(1, 'Some random department name', 'SomeLocation');
exception
    when ORA_12899 then
        dbms_output.put_line('Cannot store the value!');
end;
/

下面的代码会有一个VALUE_ERROR;

DECLARE
   ORA_12899 EXCEPTION;
   PRAGMA EXCEPTION_INIT(ORA_12899, -12899);
   v_dept VARCHAR2(20);
begin
    v_dept := 'Some random department name';
    insert into department values(1, v_dept, 'SomeLocation');
exception
    when ORA_12899 then
        dbms_output.put_line('Cannot store the value!');
end;
/

【讨论】:

这行得通。但是你能告诉我为什么 value_error 不是引发的异常,尽管它是根据文档应该引发的异常吗? ORA-12899 - 当您将(这可能在 INSERT/UPDATE/MERGE 语句中)文本放入列但文本的长度大于列的数据长度时引发。 VALUE_ERROR - 请参阅此问题的其他答案,因为它有更大的解释。在您的代码中,它将是 ORA-12899,因为您将值放入列中,但是如果您有 DECLARE 变量并分配了一个长度大于 20 的值,则会引发 VALUE_ERROR,请参阅我的更新答案

以上是关于PL/SQL value_error 异常没有被捕获的主要内容,如果未能解决你的问题,请参考以下文章

强制值为空时无法引发 VALUE_ERROR

为啥在匿名 PL/SQL 块中没有立即引发异常?

PL/SQL 没有发现游标的数据异常

Oracle的PL_SQL的异常处理

约束违反异常 PL/SQL

PL/SQL异常处理: