捕获导致 ORA-01438 的列:值大于此列允许的指定精度

Posted

技术标签:

【中文标题】捕获导致 ORA-01438 的列:值大于此列允许的指定精度【英文标题】:Capture the column causing ORA-01438: value larger than specified precision allowed for this column 【发布时间】:2019-08-07 05:09:26 【问题描述】:

我正在使用 Oracle 12C。 如果我的插入语句因 ORA-01438 失败,我如何捕获导致错误的列。例如看下面的代码-

create table T1  ( c1 number(3,2) , c2 number(4,2), c3 number(5,2) );

insert into T1 ( c1 ,c2, c3)  values ( 1, 22,333); --good 

commit;

insert into T1 ( c1 ,c2, c3)  values ( 1, 22,3330); --ORA-01438 for c1

insert into T1 ( c1 ,c2, c3)  values ( 1, 222,3330); ---ORA-01438 for c1, c2

insert into T1 ( c1 ,c2, c3)  values ( 11, 222,3330); --ORA-01438 for c1, c2, c3

我什至尝试过 DBMS_ERRLOG.CREATE_ERROR_LOG 但我无法识别导致错误数据的列。请看下面的代码-

EXECUTE DBMS_ERRLOG.CREATE_ERROR_LOG('T1', 'T1_bad');

insert into T1 ( c1 ,c2, c3)   values ( 11, 222,3330);

log errors into T1_bad;

SELECT  * FROM T1_bad;

【问题讨论】:

恐怕无法使用DBMS_ERRLOG获取列名。 可能重复 -- ORA-01438: value larger than specified precision allows for this column - How do i get which column it is referring to? 【参考方案1】:

您可以设置事件来追踪罪魁祸首:

ALTER SESSION SET EVENTS='1438 TRACE NAME ERRORSTACK FOREVER, LEVEL 12';

以下代码显示了相同的演示:

SQL> create table test (name varchar2(1), name1 varchar2(1));

Table created.

SQL> ALTER SESSION SET EVENTS='1438 TRACE NAME ERRORSTACK FOREVER, LEVEL 12';

Session altered.

SQL> insert into test values('ad','a');
insert into test values('ad','a')
                        *
ERROR at line 1:
ORA-12899: value too large for column "TEJASH"."TEST"."NAME" (actual: 2, maximum:
1)


SQL> insert into test values('d','ad');
insert into test values('d','ad')
                            *
ERROR at line 1:
ORA-12899: value too large for column "TEJASH"."TEST"."NAME1" (actual: 2, maximum:
1)


SQL>

干杯!!

【讨论】:

解决方案不适用于数字,因为引发了ORA-01438,它没有列信息。 是的,对于 NUMBER 列,错误是 ORA-1438,对于 VARCHAR2,错误是 ORA-12899。如果它是数字,您将不会获得该列名。您可以使用 SQL*Plus,它会在导致错误的列值下显示 *。但是,我知道这是手动选项。【参考方案2】:

我找到的一个解决方案是使用动态 sql (How can I get position of an error in Oracle SQL query?) 然后DBMS_SQL.LAST_ERROR_POSITION 来获取错误位置:

DECLARE
  c   INTEGER := DBMS_SQL.open_cursor ();
  erg INTEGER;
  l_sql VARCHAR2(4000) := 'INSERT INTO test(id, description) VALUES (3333, ''Test'')';
BEGIN
  DBMS_SQL.parse (c, l_sql, DBMS_SQL.native);
  erg := DBMS_SQL.EXECUTE(c);
  DBMS_SQL.close_cursor (c);
EXCEPTION
  WHEN OTHERS THEN
    dbms_output.put_line(sqlerrm);
    dbms_output.put_line(l_sql);
    dbms_output.put_line(LPAD('*', DBMS_SQL.LAST_ERROR_POSITION+1));
    DBMS_SQL.close_cursor (c);
END;

输出:

ORA-01438: ...
INSERT INTO test(id, description) VALUES (3333, 'Test')
                                          *

【讨论】:

以上是关于捕获导致 ORA-01438 的列:值大于此列允许的指定精度的主要内容,如果未能解决你的问题,请参考以下文章

插入 3 时出现“ORA-01438: 值大于此列允许的指定精度”

插入 3 时出现“ORA-01438: 值大于此列允许的指定精度”

错误:“ORA-01438:值大于此列允许的指定精度”故障因素:“空”详细信息:org.kxml2.kdom.Node@99c0b9c

ORA-01438: 该列允许的值大于指定的精度

ORA-01438 错误

EBS_DBA_问题:关于ORA-01438: value larger than specified precision allowed for this column