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

Sql 标识在DML操作期间生成错误的行,sql,oracle,plsql,stack-trace,Sql,Oracle,Plsql,Stack Trace,我们有一个表EVAPP_接口,它没有在许多数字列上指定刻度或精度。我们需要修改列定义以添加适当的比例和精度,但不能更改表中列的顺序。为了实现这一点,我们正在做以下工作 我们将所有数据复制到一个新表EVI 我们将现有EVAPP_接口表中的数字列设置为NULL 我们更改EVAPP_接口列的精度 我们把数据复制回来 但是,当数据被复制回时,某些行会生成异常,因为它们超过了新的比例和/或精度设置(即,本应存储利率的列中的值为10亿) 我想确定哪些列和哪些行有这些错误数据 首先是复制表 select

我们有一个表
EVAPP_接口
,它没有在许多数字列上指定刻度或精度。我们需要修改列定义以添加适当的比例和精度,但不能更改表中列的顺序。为了实现这一点,我们正在做以下工作

  • 我们将所有数据复制到一个新表
    EVI
  • 我们将现有
    EVAPP_接口
    表中的数字列设置为
    NULL
  • 我们更改
    EVAPP_接口
    列的精度
  • 我们把数据复制回来
但是,当数据被复制回时,某些行会生成异常,因为它们超过了新的比例和/或精度设置(即,本应存储利率的列中的值为10亿)

我想确定哪些列和哪些行有这些错误数据

首先是复制表

 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';
因此,我不能完全确定SQLERRM和SQLCODE是否会给出完整的堆栈跟踪。而且,我没有足够的数据来验证这一点。是否有人可以确认我是否可以找到导致问题的特定列?我已经为大多数列提供了数字(14,2)作为精度,如果可能的话,我希望删除坏数据,而不是提高精度。由于它是生产数据,我不允许导入数据来检查它。

您可能想使用它来记录所有有问题数据的行

我不知道为什么到处都使用动态SQL——在脚本之外创建表比每次删除和重新创建表要传统得多。这将允许您使用静态SQL引用表,并允许您将大量错误检查转移到编译阶段而不是执行阶段。不过,我假设您有充分的理由希望它完全是动态的

您需要创建一个错误表(如果要删除基表,则需要删除错误表,以便重新创建它)。并且您需要修改
插入
,将
日志错误添加到
。差不多

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_界面
,同时将任何故障写入
EVAPP_ERROR
(我们在上述步骤中创建的错误表)。

是的,此脚本是卷展/升级的一部分,因此需要同时进行错误检查和插入。这是一个惊人的实用程序,我希望我以前发现过它。但是,我注意到带有DML错误日志记录的脚本在运行时与错误无关,并修改了精度,同时将错误记录在EVAPP_error中。那么,它只是跳过了有错误的行吗?看起来它从主表中删除了那些坏行。@roymustang86-有错误的行将被写入错误表(连同错误描述),可以成功插入的行将被成功插入。您必须确定修复有问题数据的最佳方法,然后您可以仅重新处理错误表中的那些行,也可以修复源中的数据并重新运行整个转换。如果希望
插入
在N次失败后停止处理,可以指定
拒绝限制
而不是指定
无限
 execute immediate 'INSERT INTO EVAPP_INTERFACE SELECT * from EVI';
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';