DBMS_OUTPUT
パッケージによって、ストアド・プロシージャ、パッケージおよびトリガーからメッセージを送信できます。このパッケージは、PL/SQLデバッグ情報の表示に特に便利です。
この章では、次の項目について説明します。
概要
セキュリティ・モデル
使用上の注意
例外
ルールおよび制限
例
表タイプ
オブジェクト・タイプ
この項では、DBMS_OUTPUT
パッケージの使用に関連する項目について説明します。
通常、このパッケージは、デバッグに使用されるか、あるいはメッセージとレポート(プロシージャにSQLコマンドDESCRIBE
を適用するなどして生成)をSQL*DBAまたはSQL*Plusに表示するために使用されます。
このパッケージに含まれているPUTプロシージャおよびPUT_LINEプロシージャによって、別のトリガー、プロシージャまたはパッケージで読み込めるバッファに情報を設定できます。別のPL/SQLプロシージャまたは無名ブロックでは、GET_LINEプロシージャおよびGET_LINESプロシージャをコールして、バッファに入れた情報を表示できます。
パッケージを無効にすると、サブプログラムに対するすべてのコールが無視されます。これによって、クライアントが情報を処理できる場合のみにサブプログラムが使用可能になるように、アプリケーションを設計できます。
dbmsotpt.sql
スクリプトは、ユーザーSYS
として実行する必要があります。これによって、パブリック・シノニムDBMS_OUTPUT
が作成され、このパッケージに対するEXECUTE
許可がpublic
に付与されます。
GET_LINE
をコールしない場合、またはSQL*Plusのスクリーンにメッセージを表示しない場合、バッファに入れたメッセージは無視されます。
SQL*Plusは、SQL文または無名PL/SQLコールを発行した後にGET_LINES
をコールします。
SQL*PlusにSET
SERVEROUTPUT
ON
を入力すると、次のコマンドが実行されます。
DBMS_OUTPUT.ENABLE (buffer_size => NULL);
この場合、出力に制限はありません。
通常は、アプリケーション・コードでDISABLEプロシージャまたはENABLEプロシージャを起動しないでください。SQL*Plusなどの外部ツールによって出力を表示するかどうかを制御できなくなる可能性があるためです。
注意: DBMS_OUTPUT を使用して送信するメッセージは、送信サブプログラムまたはトリガーが完了するまでは実際に送信されません。プロシージャの実行中に出力をフラッシュするメカニズムはありません。 |
例1: トリガーを使用した出力
トリガーを使用して、デバッグ処理の結果を出力できます。たとえば、次のコマンドを実行するトリガーをコード化できます。
DBMS_OUTPUT.PUT_LINE('I got here:'||:new.col||' is the new value');
DBMS_OUTPUT
パッケージを使用可能にした場合、このPUT_LINE
によって生成されたテキストはバッファに入れられ、トリガー文(トリガーを起動させるINSERT
、DELETE
またはUPDATE
が想定できます)の実行後に、情報行を取り出すことができます。次に例を示します。
BEGIN DBMS_OUTPUT.GET_LINE(:buffer, :status); END;
これによって、スクリーンにバッファを表示できます(オプション)。status
が0(ゼロ)以外で戻るまで、GET_LINE
へのコールを繰り返します。パフォーマンス向上のためには、行の配列を戻すことができるGET_LINESプロシージャへのコールを使用してください。
例2: ストアド・プロシージャとトリガーのデバッグ
DBMS_OUTPUT
パッケージは、一般的に、ストアド・プロシージャおよびトリガーをデバッグするために使用されます。また、「例3: オブジェクトに関する情報の取得」で示すように、このパッケージを使用すると、オブジェクトの情報を取り出し、その出力をフォーマットできます。
このファンクションは、従業員表を問い合せて、指定部門の給与合計を戻します。このファンクションには、次のようにPUT_LINE
プロシージャへのコールがいくつか含まれます。
CREATE FUNCTION dept_salary (dnum NUMBER) RETURN NUMBER IS CURSOR emp_cursor IS SELECT sal, comm FROM emp WHERE deptno = dnum; total_wages NUMBER(11, 2) := 0; counter NUMBER(10) := 1; BEGIN FOR emp_record IN emp_cursor LOOP emp_record.comm := NVL(emp_record.comm, 0); total_wages := total_wages + emp_record.sal + emp_record.comm; DBMS_OUTPUT.PUT_LINE('Loop number = ' || counter || '; Wages = '|| TO_CHAR(total_wages)); /* Debug line */ counter := counter + 1; /* Increment debug counter */ END LOOP; /* Debug line */ DBMS_OUTPUT.PUT_LINE('Total wages = ' || TO_CHAR(total_wages)); RETURN total_wages; END dept_salary;
EMP
表には、次の行が含まれているとします。
EMPNO SAL COMM DEPT ----- ------- -------- ------- 1002 1500 500 20 1203 1000 30 1289 1000 10 1347 1000 250 20
ユーザーがSQL*Plusの次の文を実行したとします。
SET SERVEROUTPUT ON VARIABLE salary NUMBER; EXECUTE :salary := dept_salary(20);
出力ペインには、次の情報が表示されます。
Loop number = 1; Wages = 2000 Loop number = 2; Wages = 3250 Total wages = 3250 PL/SQL procedure successfully executed.
例3: オブジェクトに関する情報の取得
この例では、ユーザーはすでにEXPLAIN
PLAN
コマンドを使用して、ある文の実行計画に関する情報を取り出し、その情報をPLAN_TABLE
に格納してあります。また、ユーザーはこの文に文IDを割り当ててあります。EXPLAIN_OUT
プロシージャの例では、表から情報を取り出し、出力をネスト形式でフォーマットして、SQL文を処理するステップの順序を厳密に記述しています。
/****************************************************************/ /* Create EXPLAIN_OUT procedure. User must pass STATEMENT_ID to */ /* to procedure, to uniquely identify statement. */ /****************************************************************/ CREATE OR REPLACE PROCEDURE explain_out (statement_id IN VARCHAR2) AS -- Retrieve information from PLAN_TABLE into cursor EXPLAIN_ROWS. CURSOR explain_rows IS SELECT level, id, position, operation, options, object_name FROM plan_table WHERE statement_id = explain_out.statement_id CONNECT BY PRIOR id = parent_id AND statement_id = explain_out.statement_id START WITH id = 0 ORDER BY id; BEGIN -- Loop through information retrieved from PLAN_TABLE: FOR line IN explain_rows LOOP -- At start of output, include heading with estimated cost. IF line.id = 0 THEN DBMS_OUTPUT.PUT_LINE ('Plan for statement ' || statement_id || ', estimated cost = ' || line.position); END IF; -- Output formatted information. LEVEL determines indention level. DBMS_OUTPUT.PUT_LINE (lpad(' ',2*(line.level-1)) || line.operation || ' ' || line.options || ' ' || line.object_name); END LOOP; END;
DBMS_OUTPUT
パッケージは、GET_LINESプロシージャで使用するために、2つのコレクション・タイプを宣言します。
このパッケージ・タイプは、PUTプロシージャおよびPUT_LINEプロシージャを介して送信されたテキストを取得するために、GET_LINESプロシージャで使用されます。
表100-2 DBMS_OUTPUTパッケージのサブプログラム
サブプログラム | 説明 |
---|---|
|
メッセージの出力を使用禁止にします。 |
|
メッセージの出力を使用可能にします。 |
|
バッファから1行取り出します。 |
|
バッファから行の配列を1つ取り出します。 |
|
|
|
行の一部をバッファに設定します。 |
|
行をバッファに設定します。 |
このプロシージャは、PUT
、PUT_LINE
、NEW_LINE
、GET_LINE
およびGET_LINES
へのコールを使用禁止にして、残っている情報のバッファをパージします。
ENABLEプロシージャと同様に、SQL*PlusのSERVEROUTPUT
オプションを使用する場合は、このプロシージャをコールする必要はありません。
このプロシージャは、PUT
、PUT_LINE
、NEW_LINE
、GET_LINE
およびGET_LINES
へのコールを使用可能にします。DBMS_OUTPUT
パッケージがアクティブ化されていない場合、これらのプロシージャへのコールは無視されます。
このプロシージャは、バッファに入れられた単一行の情報を取り出します。
使用上の注意
単一行または行の配列をバッファから取り出すことができます。バッファに入れられた単一行の情報を取り出すには、GET_LINE
プロシージャをコールします。サーバーへのコール数を減らすには、GET_LINES
プロシージャをコールして、バッファから行の配列を取り出します。
SQL*Plusを使用している場合は、特別のSET
SERVEROUTPUT
ON
コマンドを使用して、この情報を自動的に表示できます。
GET_LINE
またはGET_LINES
をコールしてから、次にPUT
、PUT_LINE
またはNEW_LINE
をコールする前に取り出されなかった行は、次のメッセージとの混同を避けるために廃棄されます。
このプロシージャは、バッファから行の配列を取り出します。
構文
DBMS_OUTPUT.GET_LINES ( lines OUT CHARARR, numlines IN OUT INTEGER); DBMS_OUTPUT.GET_LINES ( lines OUT DBMSOUTPUT_LINESARRAY, numlines IN OUT INTEGER);
使用上の注意
単一行または行の配列をバッファから取り出すことができます。バッファに入れられた単一行の情報を取り出すには、GET_LINE
プロシージャをコールします。サーバーへのコール数を減らすには、GET_LINES
プロシージャをコールして、バッファから行の配列を取り出します。
SQL*Plusを使用している場合は、特別のSET
SERVEROUTPUT
ON
コマンドを使用して、この情報を自動的に表示できます。
GET_LINE
またはGET_LINES
をコールしてから、次にPUT
、PUT_LINE
またはNEW_LINE
をコールする前に取り出されなかった行は、次のメッセージとの混同を避けるために廃棄されます。
このプロシージャは、行端マーカーを設定します。GET_LINEプロシージャおよびGET_LINESプロシージャは、改行で区切られた行を戻します。PUT_LINEプロシージャまたはNEW_LINEプロシージャへのすべてのコールによって、GET_LINE
(S
)で戻される行が生成されます。
このプロシージャは、行の一部をバッファに設定します。
注意: NUMBER データ・タイプを使用するPUT プロシージャは使用されなくなります。現在はサポートされますが、このリリースに含まれているのは下位互換性を保つという理由にすぎません。 |
使用上の注意
PUT
を複数回コールすることによって個別に情報行を作成するか、PUT_LINE
をコールして情報行全体をバッファに設定することができます。
PUT_LINE
をコールすると、指定した項目には行端マーカーが自動的に付きます。PUT
をコールして行を作成する場合は、NEW_LINE
をコールして行端マーカーを追加する必要があります。GET_LINE
およびGET_LINES
は、改行文字で終了していない行は戻しません。
行が行制限を超えた場合は、エラー・メッセージを受信します。
PUT
またはPUT_LINE
で作成した出力はバッファに入れられます。この出力は、それをバッファに入れたPL/SQLプログラム・ユニットがコール元に戻るまで取り出せません。
たとえば、SQL*Plusは、PL/SQLプログラムが完了するまでDBMS_OUTPUT
メッセージを表示しません。PL/SQLプログラム内でDBMS_OUTPUT
バッファをフラッシュするメカニズムはありません。
SQL> SET SERVEROUTPUT ON SQL> BEGIN 2 DBMS_OUTPUT.PUT_LINE ('hello'); 3 DBMS_LOCK.SLEEP (10); 4 END;
このプロシージャは、行をバッファに設定します。
注意: NUMBER データ・タイプを使用するPUT_LINE プロシージャは使用されなくなります。現在はサポートされますが、このリリースに含まれているのは下位互換性を保つという理由にすぎません。 |
使用上の注意
PUT
を複数回コールすることによって個別に情報行を作成するか、PUT_LINE
をコールして情報行全体をバッファに設定することができます。
PUT_LINE
をコールすると、指定した項目には行端マーカーが自動的に付きます。PUT
をコールして行を作成する場合は、NEW_LINE
をコールして行端マーカーを追加する必要があります。GET_LINE
およびGET_LINES
は、改行文字で終了していない行は戻しません。
行が行制限を超えた場合は、エラー・メッセージを受信します。
PUT
またはPUT_LINE
で作成した出力はバッファに入れられます。この出力は、それをバッファに入れたPL/SQLプログラム・ユニットがコール元に戻るまで取り出せません。
たとえば、SQL*Plusは、PL/SQLプログラムが完了するまでDBMS_OUTPUT
メッセージを表示しません。PL/SQLプログラム内でDBMS_OUTPUT
バッファをフラッシュするメカニズムはありません。次に例を示します。
SQL> SET SERVEROUTPUT ON SQL> BEGIN 2 DBMS_OUTPUT.PUT_LINE ('hello'); 3 DBMS_LOCK.SLEEP (10); 4 END;