SQL*Loaderをはじめて使った際にいろいろエラーが出て少し苦労したのでそれをメモしておきます。
■OPTIONALLY ENCLOSED忘れ
CSVファイルに「"」がついているのに、ロード時のオプションで指定し忘れた場合に出たエラーです。
# DIRECTなし、日付型のときに出た
ORA-01841: (full) year must be between -4713 and +9999, and not be 0
# DIRECT、日付型のときに出た
ORA-26041: DATETIME/INTERVALデータ型の変換エラーが発生しました
# DIRECTなし、(カラムの最大長まで入れている)文字列型のときに出る
ORA-12899: value too large for column カラム名 (actual: 10, maximum: 8)
# DIRECT、(カラムの最大長まで入れている)文字列型のときに出る
ORA-12899: 列カラム名の値が大きすぎます(実際: 10、最大: 8)
これらが出た場合には「OPTIONALLY ENCLOSED」の指定を疑ってみましょう。
文字列型の場合のエラーは比較的分かりやすいと思いますが、日時型の場合のエラーは少し気付きにくいかもしれません。
特にORA-26041は、ヘルプのページにこう書いてあります。
ORA-26041: DATETIME/INTERVALデータ型の変換エラーが発生しました
原因: 列をDATETIMEデータ型から内部DATETIME/CHARACTERデータ型に変換できませんでした。
処置: オラクル社カスタマ・サポート・センターに連絡してください。
サポート・センターに連絡するしかない、と。そんなエラーが出ると途方にくれがちですが、サポート・センターに連絡しなくても簡単に対応できますので、落ち着いて対処しましょう。
■日時形式
CSVファイルの日時系のカラムの書式と現在のセッションの日時系の書式が異なる場合に出たエラーです。
ORA-01861: リテラルが書式文字列と一致しません
出力時と入力時で書式が異なるだけなので、あわせればOKです。
- to_char関数でCSV出力時のフォーマットを変更する
- NLS_DATE_FORMAT・NLS_TIMESTAMP_FORMATでCSV出力時のフォーマットを変更する
- NLS_DATE_FORMAT・NLS_TIMESTAMP_FORMATで入力時のフォーマットを変更する
のいずれかが必要です。
出力時も入力時も
ALTER SESSION SET NLS_DATE_FORMAT = "YYYY/MM/DD HH24:MI:SS";
ALTER SESSION SET NLS_TIMESTAMP_FORMAT = "YYYY/MM/DD HH24:MI:SSXFF";
などと統一しておくことが望ましいと思います。
■DIRECT+APPEND
以下の条件を満たす場合に問題が発生しました。
- DIRECT+APPENDをしている
- 主キーが存在するテーブルに対する処理
- テーブルに存在するデータと同じデータを取込んだ
※sqlloader実行時にはエラーは出ません
DIRECT+APPENDだと、主キーが重複していてもかまわず追加します。その結果、インデックスが壊れます。壊れたあとは一応検索処理自体はできるのですが、インデックス検索が不可能になり、どんな検索でも「TABLE ACCESS FULL」になります。
INSERTやDELETEを行なおうとすると以下のエラーが出ます。
ORA-01502: index 'インデックス名' or partition of such index is in unusable state
ORA-01502: 索引'インデックス名'またはそのパーティションが使用不可の状態です。
原因が分かりませんが以下のエラーも出ました。
ORA-00604: error occurred at recursive SQL level 1
ORA-00054: resource busy and acquire with NOWAIT specified
※対象テーブルをtruncateしたら回復しました。
DIRECT+APPENDの組み合わせは危険なので避けたほうがいいと思います。
ちなみにDIRECTでAPPENDなしでキー重複のデータを入れようとした場合には、データがある場合に以下のエラーが発生します。
SQL*Loader-601: INSERTオプションの場合、表は空である必要があります。表…でエラーが発生しました。
2011/10/18