47

プロシージャの時間を把握するために pl/sql でデバッグする必要があります。

SELECT systimestamp FROM dual INTO time_db;
DBMS_OUTPUT.PUT_LINE('time before procedure ' || time_db);

しかし、出力がどこに行くのか、収集したいすべてのデータを含むログ ファイルにリダイレクトするにはどうすればよいのかわかりません。

4

10 に答える 10

38

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
于 2009-09-21T10:05:18.063 に答える
33

ファイルへの書き込みの代わりに、テーブルへの書き込みはどうですか? 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 つの方法は、毎晩/毎週実行され、「古い」デバッグ メッセージを削除するジョブです。

于 2009-09-21T10:34:46.007 に答える
16

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 は、他の方法で出力を取得できますが、その方法についてはよくわかりません。

于 2009-09-21T09:24:56.057 に答える
5

Tony の回答に加えて、PL/SQL プログラムがどこで時間を費やしているかを知りたい場合は、Oracle PL/SQL ドキュメントのこの部分を確認することも価値があります。

于 2009-09-21T10:41:35.853 に答える
3

補足として、この出力はすべてサーバー側で生成されることに注意してください。

DBMS_OUTPUTを使用すると、クエリの実行中にサーバーでテキストが生成され、バッファに格納されます。サーバーがクエリデータの取得を完了すると、クライアントアプリにリダイレクトされます。つまり、この情報はクエリが終了したときにのみ取得されます。

UTL_FILEを使用すると、ログに記録されたすべての情報がサーバー内のファイルに保存されます。実行が終了したら、このファイルに移動して情報を取得する必要があります。

お役に立てれば。

于 2009-09-21T09:50:04.693 に答える
3

UTL_FILEの代わりに使用するDBMS_OUTPUTと、出力がファイルにリダイレクトされます。

http://oreilly.com/catalog/oraclebip/chapter/ch06.html

于 2009-09-21T09:11:50.497 に答える
1

データベースをホストする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
于 2016-09-23T14:09:55.477 に答える
-1

古いスレッドですが、別の代替手段があります。

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'));

それが役に立てば幸い。

于 2016-07-20T14:29:01.430 に答える