2009-09-21 20 views
40

ich in PL/SQL debuggen müssen Zeiten der Verfahren auf Figur möchte ich verwenden:Wie wird die Ausgabe von DBMS_OUTPUT.PUT_LINE in eine Datei umgeleitet?

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

aber ich verstehe nicht, wo der Ausgang geht und wie kann ich umleiten es in eine Log-Datei, die enthält alle Daten, die ich sammeln möchte?

Antwort

3

Mit UTL_FILE statt DBMS_OUTPUT ausgegeben in eine Datei umleiten:

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

+0

dank für die schnelle Antwort :) werde ich versuchen, dies ein Versuch zu geben (aber es sou nds wirklich schwierig, es zu funktionieren), haben Sie eine Idee, wie man das DBMS_OUTPUT zu einer Datei druckt (es kann einfacher sein) –

12

Wenn Sie gerade Ihre PL/SQL in SQL Testen Plus können Sie es in eine Datei ausgeben:

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 

IDEs wie Toad und SQL Developer können die Ausgabe auf andere Arten erfassen, aber ich bin nicht vertraut mit wie.

+0

danke, aber ich teste eine andere Anwendung, die die pl/sql db verwendet und ich brauche Die Informationen, die in einer Datei gespeichert werden, während das .sql-Skript nicht vom sqldeveloper ausgeführt wird, irgendwelche Ideen? –

+0

Nun, Sie können die Ausgabe von DBMS_OUTPUT in der aufrufenden Anwendung durch den Aufruf von DBMS_OUTPUT.ENABLE vor dem Schreiben von Nachrichten erhalten, und rufen Sie dann DBMS_OUTPUT.GET_LINE oder GET_LINES. Um diese Information dann in eine Datei zu bringen, würde es erforderlich sein, eine eigene Datei zu öffnen/schreiben/zu schließen, z. mit UTL_FILE - in diesem Fall können Sie auch UTL_FILE in erster Linie verwenden! –

3

Als eine Randnotiz, denken Sie daran, dass alle diese Ausgabe auf der Serverseite generiert wird.

Mit DBMS_OUTPUT wird der Text auf dem Server generiert, während er Ihre Abfrage ausführt und in einem Puffer speichert. Es wird dann zu Ihrer Client-App umgeleitet, wenn der Server den Abfragedatenabruf beendet hat. Das heißt, Sie erhalten diese Informationen erst, wenn die Abfrage beendet ist.

Mit UTL_FILE werden alle protokollierten Informationen in einer Datei auf dem Server gespeichert. Wenn die Ausführung abgeschlossen ist, müssen Sie zu dieser Datei navigieren, um die Informationen zu erhalten.

Hoffe, das hilft.

35

DBMS_OUTPUT ist nicht das beste Tool zum Debuggen, da die meisten Umgebungen es nicht nativ verwenden. Wenn Sie jedoch die Ausgabe von DBMS_OUTPUT erfassen möchten, verwenden Sie einfach die DBMS_OUTPUT.get_line Prozedur.

Hier ist ein kleines Beispiel:

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 
+0

Wie definieren Sie Variablen 'l_line VARCHAR2 (255); l_done NUMMER; l_file utl_file.file_type; '? –

+0

VARCHAR2, NUMBER sind [Standard-SQL-Datentypen] (http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/datatypes.htm#CHDHAEGF). ['UTL_FILE'] (http://docs.oracle.com/cd/E11882_01/appdev.112/e25788/u_file.htm#BABGGEDF) ist ein Standardpaket. –

29

Als Alternative zu einer Datei zu schreiben, wie etwa an einen Tisch zu schreiben? Stattdessen DBMS_OUTPUT.PUT_LINE zu nennen könnten Sie Ihre eigen DEBUG.OUTPUT Prozedur etwas wie nennen:

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; 

Die Verwendung einer autonomen Transaktion ermöglicht es Ihnen, Debug-Meldungen von Transaktionen erzeugt zu behalten, die zurückgesetzt erhalten (zB nach einer Ausnahme angehoben), wie es passieren würde, wenn Sie eine Datei verwenden würden.

Die boolesche Variable g_debugging ist eine Paketvariable, die standardmäßig auf "false" gesetzt und auf "true" gesetzt werden kann, wenn eine Debug-Ausgabe erforderlich ist.

Natürlich müssen Sie diese Tabelle so verwalten, dass sie nicht für immer wächst! Ein Weg wäre ein Job, der jede Nacht/Woche läuft und alle Debug-Nachrichten löscht, die "alt" sind.

+1

+1 für die Beantwortung der eigentlichen zugrunde liegenden Frage ("Wie melde ich mich von Oracle?") anstelle der scheinbaren Frage. –

5

Zusätzlich zu Tonys Antwort, wenn Sie herausfinden möchten, wo Ihr PL/SQL-Programm seine Zeit verbringt, lohnt es sich auch, einen Teil der Oracle PL/SQL-Dokumentation zu lesen this.

+0

+1 für DBMS_PROFILER. Es ist immer besser, ein eingebautes Oracle wann immer möglich zu verwenden. – APC

+0

Ja, das ist ein sehr nützlicher Tipp. –

13

verwenden set serveroutput on;

zum Beispiel:

set serveroutput on; 

DECLARE 
x NUMBER; 
BEGIN 
x := 72600; 
dbms_output.put_line('The variable X = '); dbms_output.put_line(x); 
END; 
-4

Try This:

SELECT systimestamp INTO time_db FROM dual ; 

DBMS_OUTPUT.PUT_LINE('time before procedure ' || time_db); 
+0

Warum sollten wir das überhaupt versuchen? –

-1

Einen alten Faden, aber es ist eine weitere Alternative.

Seit 9i können Sie die Pipeline-Tabellenfunktion verwenden.

zunächst eine Art als eine Tabelle von varchar erstellen:

CREATE TYPE t_string_max IS TABLE OF VARCHAR2(32767); 

Zweitens wickeln Sie den Code in einer Pipeline-Funktionsdeklaration:

CREATE FUNCTION fn_foo (bar VARCHAR2) -- your params 
    RETURN t_string_max PIPELINED IS 
    -- your vars 
BEGIN 
    -- your code 
END; 
/

alle DBMS_OUTPUT.PUT_LINE für PIPE ROW ersetzen.

Schließlich es so nennen:

SELECT * FROM TABLE(fn_foo('param')); 

Hoffe, es hilft.

1

Es ist möglich, eine Datei direkt auf den DB-Server zu schreiben, auf dem sich Ihre Datenbank befindet. Dies ändert sich mit der Ausführung Ihres PL/SQL-Programms.

Dies nutzt die Oracle directoryTMP_DIR; Sie haben es zu erklären, und die unten stehende Prozedur erstellen:

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; 
/

Hier ist, wie es zu benutzen:

1) Starten Sie diese von Ihrem SQL * PLUS-Client:

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) auf dem Datenbankserver, öffnen sie eine Shell und

 
    tail -f -n500 /directory/where/oracle/can/write/on/DB_server/my_output.log