0

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

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

然而,当数据被复制回来时,一些行会产生异常,因为它们超出了新的比例和/或精度设置(即,应该存储利率的列中的值 10 亿)。

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) 作为大多数列的精度,如果可能的话,我想删除坏数据而不是提高精度。而且由于是生产数据,我不允许导入数据进行检查。

4

1 回答 1

1

您可能希望使用DML 错误日志记录所有有问题数据的行。

我不确定你为什么到处都使用动态 SQL——在脚本之外创建表而不是每次都删除和重新创建它会更加传统。这将允许您使用静态 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(我们在上面的步骤中创建的错误表)。

于 2012-07-23T20:55:11.503 回答