0

We have a table EVAPP_INTERFACE that did not specify a scale or precision on a number of numeric columns. We need to modify the column definition to add appropriate scale and precision but we cannot change the order of the columns in the table. In order to accomplish this, we are doing the following

  • We copy all the data to a new table EVI
  • We set the numeric columns in the existing EVAPP_INTERFACE table to NULL
  • We change the precision of the EVAPP_INTERFACE columns
  • We copy the data back

When the data is copied back, however, some rows generate an exception because they exceed the new scale and/or precision settings (i.e. a value of 1 billion in a column that is supposed to store an interest rate).

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

I want to identify which column and which rows have this bad data.

First the duplicate table

 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';

Then, I change precisions: There are 226 such blocks throughtout the script.

 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; 

Then, I insert back the old data. This is where it bombs

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

So, I am not entirely sure if SQLERRM and SQLCODE will give the full stacktrace. And, I don't have enough dataset to verify this. Can anyone confirm if there is anyway that I can find out which particular column is causing the issue? I have already provided NUMBER(14,2) as the precision for most columns, and if possible I want to erase the bad data instead of increasing precision. And since it is production data, I am not allowed to import the data to inspect it.

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 に答える