プロシージャの時間を計算するには、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つの方法は、夜間/毎週実行し、「古い」デバッグメッセージを削除するジョブです。
SQL PlusでPL/SQLをテストするだけの場合は、次のようなファイルに転送できます。
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は他の方法で出力をキャプチャできますが、その方法についてはよく知りません。
set serveroutput onを使用します。
例えば:
set serveroutput on;
DECLARE
x NUMBER;
BEGIN
x := 72600;
dbms_output.put_line('The variable X = '); dbms_output.put_line(x);
END;
Tonyの答えに加えて、PL/SQLプログラムがどこで時間を費やしているのかを調べたい場合は、Oracle PL/SQLのドキュメントの一部である this をチェックする価値があります。
補足として、この出力はすべてサーバー側で生成されることに注意してください。
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