识别在DML操作期间生成错误的行

时间:2012-07-23 20:42:25

标签: sql oracle plsql stack-trace

我们有一个表EVAPP_INTERFACE,它没有在许多数字列上指定比例或精度。我们需要修改列定义以添加适当的比例和精度,但我们无法更改表中列的顺序。为了实现这一目标,我们正在做以下

  • 我们将所有数据复制到新表EVI
  • 我们将现有EVAPP_INTERFACE表格中的数字列设置为NULL
  • 我们更改了EVAPP_INTERFACE
  • 的精度
  • 我们将数据复制回来

但是,当复制数据时,某些行会生成异常,因为它们超出了新的比例和/或精度设置(即应该存储利率的列中的值为10亿)。 p>

ERROR : ORA-01438: value larger than specified precision allowed for this column 

我想确定哪个列以及哪些行包含此错误数据。

首先是重复的表

 select count(*) into countTab from USER_TAB_COLUMNS where TABLE_NAME = 'EVI'; 
IF  (countTab <> 0) then 
    execute immediate 'drop table EVI';
    execute immediate 'create table EVI as (select * from EVAPP_INTERFACE)'; 
ELSE
    execute immediate 'create table EVI as (select * from EVAPP_INTERFACE)'; 
END IF;
execute immediate 'TRUNCATE TABLE EVAPP_INTERFACE';

然后,我改变了精度:在剧本中有226个这样的块。

 select count(*) into countCol from USER_TAB_COLUMNS where TABLE_NAME = 'EVAPP_INTERFACE' and COLUMN_NAME = 'PST_NUM' and DATA_SCALE is null; 
  IF    (countCol <> 0) then   
 execute immediate 'alter table EVAPP_INTERFACE modify PST_NUM NUMBER(14,2)' ; 
     DBMS_OUTPUT.put_line('  EVAPP_INTERFACE.PST_NUM has been modified to the required precision'); 
END IF; 

然后,我插回旧数据。这就是轰炸的地方

 execute immediate 'INSERT INTO EVAPP_INTERFACE SELECT * from EVI';

所以,我不完全确定SQLERRM和SQLCODE是否会提供完整的堆栈跟踪。而且,我没有足够的数据集来验证这一点。任何人都可以确认我是否可以找出导致问题的特定列?我已经提供了NUMBER(14,2)作为大多数列的精度,如果可能的话我想删除坏数据而不是提高精度。由于它是生产数据,我不允许导入数据进行检查。

1 个答案:

答案 0 :(得分:1)

您可能希望使用DML Error Logging来记录有问题数据的所有行。

我不确定为什么你到处都在使用动态SQL--在脚本之外创建表而不是丢弃&amp;每次都要重新创造它。这将允许您使用静态SQL来引用该表,并允许您将大量错误检查移动到编译阶段而不是执行阶段。不过,我会假设你有充分理由希望这完全是动态的。

您需要创建一个错误表(如果您要删除基表以便重新创建它,则需要删除错误表)。您需要修改INSERT以添加LOG ERRORS INTO。像

这样的东西
dbms_errlog.create_error_table( 'EVAPP_INTERFACE', 
                                'EVAPP_ERROR' );

创建错误表和

EXECUTE IMMEDIATE 
  'INSERT INTO evapp_interface ' ||
  '  SELECT * ' ||
  '    FROM evi ' || 
  '  LOG ERRORS INTO evapp_error ' ||
  '  REJECT LIMIT UNLIMITED';

将数据插入EVAPP_INTERFACE,同时将任何失败写入EVAPP_ERROR(我们在上面的步骤中创建的错误表)。