我们有一个表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)作为大多数列的精度,如果可能的话我想删除坏数据而不是提高精度。由于它是生产数据,我不允许导入数据进行检查。
答案 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
(我们在上面的步骤中创建的错误表)。