web-dev-qa-db-fra.com

Comment rediriger la sortie de DBMS_OUTPUT.PUT_LINE vers un fichier?

J'ai besoin de déboguer en pl/sql pour comprendre le temps des procédures, je veux utiliser:

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

mais je ne comprends pas où va la sortie et comment puis-je la rediriger vers un fichier journal qui contiendra toutes les données que je veux collecter?

45
aye

DBMS_OUTPUT n'est pas le meilleur outil pour déboguer, car la plupart des environnements ne l'utilisent pas en mode natif. Si vous voulez capturer la sortie de DBMS_OUTPUT cependant, vous utiliseriez simplement le DBMS_OUTPUT.get_line procédure.

Voici un petit exemple:

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
37
Vincent Malgrat

Au lieu d'écrire dans un fichier, pourquoi ne pas écrire dans une table? Au lieu d'appeler DBMS_OUTPUT.PUT_LINE, vous pouvez appeler votre propre procédure DEBUG.OUTPUT, par exemple:

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;

L’utilisation d’une transaction autonome vous permet de conserver les messages de débogage générés à partir de transactions annulées (par exemple après la levée d’une exception), comme ce serait le cas si vous utilisiez un fichier.

La variable boolean g_debugging est une variable de package qui peut être définie par défaut sur false et définie sur true lorsque la sortie de débogage est requise.

Bien sûr, vous devez gérer cette table afin qu'elle ne croisse pas pour toujours! Une façon serait un travail qui s'exécute tous les soirs/toutes les semaines et supprime les messages de débogage "anciens".

31
Tony Andrews

Si vous testez simplement votre PL/SQL dans SQL Plus, vous pouvez le diriger vers un fichier comme celui-ci:

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

Les IDE tels que Toad et SQL Developer peuvent capturer la sortie de différentes manières, mais je ne connais pas comment.

14
Tony Andrews

utilisez set serveroutput on;

par exemple:

set serveroutput on;

DECLARE
x NUMBER;
BEGIN
x := 72600;
dbms_output.put_line('The variable X = '); dbms_output.put_line(x);
END;
14
Mahmoud Hanafy

En plus de la réponse de Tony, si vous cherchez à savoir où votre programme PL/SQL consacre son temps, cela vaut également la peine de vérifier this une partie de la documentation Oracle PL/SQL.

5
Ian Carpenter

Notez également que toute cette sortie est générée côté serveur.

À l'aide de DBMS_OUTPUT, le texte est généré sur le serveur pendant l'exécution de la requête et stocké dans une mémoire tampon. Il est ensuite redirigé vers votre application client lorsque le serveur termine la récupération des données de la requête. En d'autres termes, vous n'obtenez ces informations qu'à la fin de la requête.

Avec UTL_FILE, toutes les informations enregistrées seront stockées dans un fichier sur le serveur. Lorsque l'exécution est terminée, vous devrez accéder à ce fichier pour obtenir les informations.

J'espère que cela t'aides.

3
Juan Calero

En utilisant UTL_FILE au lieu de DBMS_OUTPUT va rediriger la sortie vers un fichier:

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

3
Rafa de Castro

Il est possible d’écrire un fichier directement sur le serveur de base de données qui héberge votre base de données, ce qui changera tout au long de l’exécution de votre programme PL/SQL.

Ceci utilise le répertoire OracleTMP_DIR; vous devez le déclarer et créer la procédure ci-dessous:

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

Voici comment l'utiliser:

1) Lancez-le à partir de votre client 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) sur le serveur de base de données, ouvrez un shell et

 tail -f -n500 /directory/where/Oracle/can/write/on/DB_server/my_output.log
1
J. Chomel