第50回 「UTL_FILEパッケージでのファイル入力」
2013.03.11
こんにちは。インストラクターの蓑島です。3月に入りすこし春らしくなってきましたね。
前回(第50回)、UTL_FILEパッケージを使った【ファイル出力(書き込み)】を解説しましたが、今回は、UTL_FILEパッケージを使った【ファイル入力(読み込み)】を解説します。
では、前回出力した DATA_PUMP_DIRディレクトリのtest.txtファイルをUTL_FILEパッケージを使って読み込んでみます。読み込んだデータで画面出力をします。
以下をご覧ください。
前回のコードと比較すると違いが分かりやすいです。
SQL> SET SERVEROUTPUT ON -- SQL*Plusの画面出力を有効
SQL> DECLARE
2 /* ファイルハンドルの宣言 */
3 FH UTL_FILE.FILE_TYPE;
4 /* 読み込んだ行を格納する変数の宣言 */
5 V_LINE VARCHAR2(32767);
6 --
7 BEGIN
8 /* 読込モード(R)で ファイルオープン ⇒ ファイルハンドル取得 */
9 FH := UTL_FILE.FOPEN('DATA_PUMP_DIR','test.txt','R');
10 --
11 LOOP
12 /* そのファイルハンドルから1行読む */
13 UTL_FILE.GET_LINE(FH,V_LINE);
14 /* その行を画面に表示する */
15 DBMS_OUTPUT.PUT_LINE(V_LINE);
16 END LOOP; -- 上記の処理を繰り返す
17 --
18 EXCEPTION
19 WHEN NO_DATA_FOUND THEN
20 /* 最後にファイルをクローズする */
21 UTL_FILE.FCLOSE(FH);
22 END;
23 /
こんにちは。 ←※ファイルに書かれていた内容です。
お元気ですか?
PL/SQLプロシージャが正常に完了しました。
では前回と違う点を重点的に解説します。
●(1)読み込んだデータを格納する変数の宣言(5行目)
ファイルからデータを読み込みますので、読み込んだデータを格納する変数が必要です。
上記の例で5行目がその変数の定義です。V_LINEという変数をVARCHAR2(32767)で宣言しました。
サイズ32767は、PL/SQLプログラムにおけるVARCHAR2の最大サイズです。
32767でなければいけないというわけではありません。
●(2)読込モードでファイルをオープンする(9行目)
前回と違って今回は読込モードでオープンします。
ポイントは、オープンモードが 'R'であるという点です。
これによりそのファイルを読み込むことができます。(ちなみに書き込みモードは'W'でしたね)
●(3)1行読み込む(13行目)
UTL_FILE.GET_LINEで、1行分のデータを変数に読み込むことができます。
構文は以下の通りです。
UTL_FILE.GET_LINE(ファイルハンドル, 変数);
(ちなみに、書き込みモードでは、1行書くとき、 UTL_FILE.PUT_LINEでしたね)
●(4) すべての行を読み込んだ終了判定処理(19行目)
UTL_FILE.GET_LINEの読み込みで終了判定処理はすこし独特なので要注意です。
まず、11~16行目のループ処理をよくご覧ください。
ファイルハンドルから1行読み込み、その行を画面表示することをループ処理で繰り返しています。
この処理を見てなにか変だと思いませんか?
終了判定処理がないですよ!?
通常、基本ループ構文( LOOP ~ END LOOP;)の中で、終了条件を判定しループから抜ける(EXIT)処理を記述していないと無限ループになります。
しかし上記の処理は無限ループにはなりません。
なぜかというと、UTL_FILE.GET_LINEが、ファイルの終端を超えてデータを読み込もうとすると、エラーとなるからです。PL/SQLではエラーが発生すると、例外処理部(EXCEPTION)に飛びます。
したがって、ループをEXITする処理を記述していなくても、無限ループにならないわけです。
そしてこの場合のエラーは、「NO_DATA_FOUND例外」です。
したがって、例外処理部のNO_DATA_FOUND例外ハンドラ(19行目)でファイルをクローズしているわけです。
「NO_DATA_FOUND例外」というと、代表的なケースは、SELECT ~INTO文が、0行の時のエラーですが、UTL_FILE.GET_LINEがファイルの終端を超えて読み込んだ場合も同じエラーなのです。
このように、最後の終了判定がすこし独特でなので注意してください。
それでは今回はここまでとします。また次回、ご期待ください。