プロシージャの時間を把握するために pl/sql でデバッグする必要があります。
SELECT systimestamp FROM dual INTO time_db;
DBMS_OUTPUT.PUT_LINE('time before procedure ' || time_db);
しかし、出力がどこに行くのか、収集したいすべてのデータを含むログ ファイルにリダイレクトするにはどうすればよいのかわかりません。
プロシージャの時間を把握するために pl/sql でデバッグする必要があります。
SELECT systimestamp FROM dual INTO time_db;
DBMS_OUTPUT.PUT_LINE('time before procedure ' || time_db);
しかし、出力がどこに行くのか、収集したいすべてのデータを含むログ ファイルにリダイレクトするにはどうすればよいのかわかりません。
DBMS_OUTPUT
ほとんどの環境ではネイティブに使用されていないため、デバッグに最適なツールではありません。ただし、出力をキャプチャする場合DBMS_OUTPUT
は、単純にDBMS_OUTPUT.get_line
手順を使用します。
以下に小さな例を示します。
SQL> create directory tmp as '/tmp/';
Directory created
SQL> CREATE OR REPLACE PROCEDURE write_log AS
2 l_line VARCHAR2(255);
3 l_done NUMBER;
4 l_file utl_file.file_type;
5 BEGIN
6 l_file := utl_file.fopen('TMP', 'foo.log', 'A');
7 LOOP
8 EXIT WHEN l_done = 1;
9 dbms_output.get_line(l_line, l_done);
10 utl_file.put_line(l_file, l_line);
11 END LOOP;
12 utl_file.fflush(l_file);
13 utl_file.fclose(l_file);
14 END write_log;
15 /
Procedure created
SQL> BEGIN
2 dbms_output.enable(100000);
3 -- write something to DBMS_OUTPUT
4 dbms_output.put_line('this is a test');
5 -- write the content of the buffer to a file
6 write_log;
7 END;
8 /
PL/SQL procedure successfully completed
SQL> host cat /tmp/foo.log
this is a test
ファイルへの書き込みの代わりに、テーブルへの書き込みはどうですか? DBMS_OUTPUT.PUT_LINE を呼び出す代わりに、次のような独自の DEBUG.OUTPUT プロシージャを呼び出すことができます。
procedure output (p_text varchar2) is
pragma autonomous_transaction;
begin
if g_debugging then
insert into debug_messages (username, datetime, text)
values (user, sysdate, p_text);
commit;
end if;
end;
自律型トランザクションを使用すると、ファイルを使用している場合に発生するように、ロールバックされたトランザクションから生成されたデバッグ メッセージを保持できます (例: 例外が発生した後)。
g_debugging ブール変数はパッケージ変数であり、デフォルトで false に設定でき、デバッグ出力が必要な場合は true に設定できます。
もちろん、そのテーブルが永遠に大きくならないように管理する必要があります。1 つの方法は、毎晩/毎週実行され、「古い」デバッグ メッセージを削除するジョブです。
PL/SQL を SQL Plus でテストするだけの場合は、次のようなファイルに送信できます。
spool output.txt
set serveroutput on
begin
SELECT systimestamp FROM dual INTO time_db;
DBMS_OUTPUT.PUT_LINE('time before procedure ' || time_db);
end;
/
spool off
Toad や SQL Developer などの IDE は、他の方法で出力を取得できますが、その方法についてはよくわかりません。
Tony の回答に加えて、PL/SQL プログラムがどこで時間を費やしているかを知りたい場合は、Oracle PL/SQL ドキュメントのこの部分を確認することも価値があります。
補足として、この出力はすべてサーバー側で生成されることに注意してください。
DBMS_OUTPUTを使用すると、クエリの実行中にサーバーでテキストが生成され、バッファに格納されます。サーバーがクエリデータの取得を完了すると、クライアントアプリにリダイレクトされます。つまり、この情報はクエリが終了したときにのみ取得されます。
UTL_FILEを使用すると、ログに記録されたすべての情報がサーバー内のファイルに保存されます。実行が終了したら、このファイルに移動して情報を取得する必要があります。
お役に立てれば。
UTL_FILE
の代わりに使用するDBMS_OUTPUT
と、出力がファイルにリダイレクトされます。
データベースをホストするDBサーバーにファイルを直接書き込む可能性があり、それはPL / SQLプログラムの実行とともにすべて変更されます。
これはOracle ディレクトリ TMP_DIR
を使用します。それを宣言し、以下のプロシージャを作成する必要があります。
CREATE OR REPLACE PROCEDURE write_log(p_log varchar2)
-- file mode; thisrequires
--- CREATE OR REPLACE DIRECTORY TMP_DIR as '/directory/where/oracle/can/write/on/DB_server/';
AS
l_file utl_file.file_type;
BEGIN
l_file := utl_file.fopen('TMP_DIR', 'my_output.log', 'A');
utl_file.put_line(l_file, p_log);
utl_file.fflush(l_file);
utl_file.fclose(l_file);
END write_log;
/
使用方法は次のとおりです。
1) SQL*PLUS クライアントからこれを起動します。
BEGIN
write_log('this is a test');
for i in 1..100 loop
DBMS_LOCK.sleep(1);
write_log('iter=' || i);
end loop;
write_log('test complete');
END;
/
2) データベース サーバーでシェルを開き、
tail -f -n500 /directory/where/oracle/can/write/on/DB_server/my_output.log
古いスレッドですが、別の代替手段があります。
9i 以降、パイプライン化されたテーブル関数を使用できます。
まず、型を varchar のテーブルとして作成します。
CREATE TYPE t_string_max IS TABLE OF VARCHAR2(32767);
次に、パイプライン化された関数宣言でコードをラップします。
CREATE FUNCTION fn_foo (bar VARCHAR2) -- your params
RETURN t_string_max PIPELINED IS
-- your vars
BEGIN
-- your code
END;
/
DBMS_OUTPUT.PUT_LINE
をすべて置き換えますPIPE ROW
。
最後に、次のように呼び出します。
SELECT * FROM TABLE(fn_foo('param'));
それが役に立てば幸い。