UTL_FILE パッケージを使ってファイル出力をする場合、PUT_LINE プロシージャを使って1行ずつ出力するのが一般的です。
この時、Oracle が自動的に出力するレコードの終端に改行コードを付けてくれるわけですが、先日奇妙な現象に遭遇しました。
データベース・キャラクタ・セットが UTF-8(AL32UTF8) の環境でファイルを出力していたのですが、ある程度大量のデータを出力しようとすると WRITE_ERROR 例外(ORA-29285: ファイル書込みエラーが発生しました。)が発生するのです。
バッファサイズも適切だし、過去にこれくらいのデータ量の出力ならいくらでもやっているし、とにかく例外が発生するようなことは全く行っていないのですが、なぜか WRITE_ERROR となります。
そこで、データ量を減らしたり、出力データの中身をみたりと、いろいろと調べているとあることに気づきました。
出力レコードの終端文字がシングルバイト文字の場合は改行コードが CRLF(0xOD 0xOA) となり、マルチバイト文字の場合は LF(0x0A) となっているのです。
そして、終端文字がマルチバイト文字のレコードを連続して出力していると、そのうち WRITE_ERROR 例外が発生するようなのです。
(どうも 32KB 程度連続して出力すると発生するような気がします...)
この現象は Oracleサーバーの NLS_LANG の設定とデータベース・キャラクタ・セットが一致していない場合に起こる現象のようです。
例えば、Windows 環境の場合、NLS_LANG の設定は JAPANESE_JAPAN.JA16SJIS であるのが普通ですが、この時、データベース・キャラクタ・セットが AL32UTF8 だと UTF-8 のコードを SHIFT-JIS のファイルに書き出すような動きになるらしく、それで改行コードがおかしくなってしまうようです。
この問題を回避するには、NLS_LANG の設定とデータベース・キャラクタ・セットを一致させるか、あるいは出力レコードの終端文字が必ずシングルバイト文字になるように出力レコードを設計するか、いずれかの方法をとらなければなりません。
まぁ、普通に設定していれば NLS_LANG の設定とデータベース・キャラクタ・セットは一致しているはずなのでこのような問題は起こらないのですが...^^;
【関連エントリ】
[Oracle] テキストファイルの入出力方法 2004/07/14
[Oracle] Linux環境でのUTL_FILEの不思議な挙動 2007/01/16
[Oracle] UTL_FILE.PUT_LINE で書き出される改行コードがおかしい! 2007/01/17
[Oracle] UTL_FILE.GET_LINE で改行コードの一部が読み込まれる! 2007/01/18
[Oracle] UTL_FILE でキャラクタ・セットを変換して読み書きする(1) 2007/02/21
[Oracle] UTL_FILE でキャラクタ・セットを変換して読み書きする(2) 2007/02/27