2009-09-21 24 views
40

tengo que depurar en PL/SQL para calcular los tiempos de los procedimientos, que desea utilizar:¿Cómo redirigir la salida de DBMS_OUTPUT.PUT_LINE a un archivo?

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

pero no entienden que la salida va y cómo puede redirigir I en un archivo de registro que contendrá todos los datos que quiero recopilar?

Respuesta

3

Usando UTL_FILE en lugar de DBMS_OUTPUT va a redirigir la salida a un archivo:

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

+0

gracias por la rápida respuesta :) voy a tratar de darle una oportunidad (pero sou es realmente difícil hacer que funcione), ¿tiene alguna idea de cómo imprimir DBMS_OUTPUT en un archivo (puede ser más fácil) –

12

Si está haciendo una prueba de su PL/SQL en SQL Plus se puede dirigir a un archivo de la siguiente manera:

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 como Toad y SQL Developer pueden capturar la salida de otras formas, pero no estoy familiarizado con cómo.

+0

gracias, pero estoy probando una aplicación diferente que utiliza el db pl/sql y necesito la información que se guardará en un archivo mientras el script .sql no se ejecuta desde sqldeveloper, ¿alguna idea? –

+0

Bien, puede obtener la salida producida por DBMS_OUTPUT en la aplicación de llamada llamando a DBMS_OUTPUT.ENABLE antes de escribir cualquier mensaje, y luego llamando a DBMS_OUTPUT.GET_LINE o GET_LINES. Pero para luego poner esa información en un archivo requeriría hacer su propio archivo de apertura/escritura/cierre, p. usando UTL_FILE - en ese caso, ¡también puede usar UTL_FILE en primer lugar! –

3

Como nota al margen, recuerde que toda esta salida se genera en el lado del servidor.

Al usar DBMS_OUTPUT, el texto se genera en el servidor mientras ejecuta su consulta y se almacena en un búfer. Luego se redirige a su aplicación cliente cuando el servidor finaliza la recuperación de datos de consulta. Es decir, solo obtiene esta información cuando finaliza la consulta.

Con UTL_FILE toda la información registrada se almacenará en un archivo en el servidor. Cuando la ejecución finalice, tendrá que navegar a este archivo para obtener la información.

Espero que esto ayude.

35

DBMS_OUTPUT no es la mejor herramienta para depurar, ya que la mayoría de los entornos no lo usan de forma nativa. Sin embargo, si desea capturar la salida DBMS_OUTPUT, simplemente use el procedimiento DBMS_OUTPUT.get_line.

Aquí hay un pequeño ejemplo:

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

¿Cómo se definen las variables 'l_line VARCHAR2 (255); l_done NUMBER; l_file utl_file.file_type; '? –

+0

VARCHAR2, NUMBER son [tipos de datos SQL estándar] (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) es un paquete estándar. –

29

Como alternativa a escribir en un archivo, la forma de escribir a una mesa? En lugar de llamar DBMS_OUTPUT.PUT_LINE se podría llamar a su propio procedimiento DEBUG.OUTPUT algo como:

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; 

El uso de una transacción autónoma le permite conservar los mensajes de depuración producidos a partir de las transacciones que consiguen deshacen (por ejemplo, después de una excepción es levantado), como sucedería si estuvieras usando un archivo.

La variable booleana g_debugging es una variable de paquete que se puede establecer de forma predeterminada como falsa y establecerse en verdadero cuando se requiere una salida de depuración.

¡Por supuesto, necesita administrar esa tabla para que no crezca para siempre! Una forma sería un trabajo que se ejecuta cada noche/semana y elimina los mensajes de depuración que son "antiguos".

+1

+1 para responder la pregunta subyacente real ("¿cómo puedo iniciar sesión desde Oracle?") en lugar de la pregunta aparente. –

5

Además de la respuesta de Tony, si está buscando saber dónde está gastando su programa PL/SQL es el momento, también vale la pena consultar this parte de la documentación de Oracle PL/SQL.

+0

+1 para DBMS_PROFILER. Siempre es mejor usar un Oracle incorporado siempre que sea posible. – APC

+0

Sí, es un consejo muy útil. –

13

use configure serveroutput on;

por ejemplo:

set serveroutput on; 

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

Prueba esto:

SELECT systimestamp INTO time_db FROM dual ; 

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

¿Por qué deberíamos intentar esto de todos modos? –

-1

Un viejo hilo, pero no hay otra alternativa.

Desde 9i puede usar la función de tabla canalizada.

En primer lugar, crear un tipo como una tabla de varchar:

CREATE TYPE t_string_max IS TABLE OF VARCHAR2(32767); 

En segundo lugar, envuelva el código de una declaración de la función pipeline:

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

Reemplazar todo DBMS_OUTPUT.PUT_LINE para PIPE ROW.

Por último, lo llaman así:

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

espero que ayude.

1

Es posible escribir un archivo directamente en el servidor de bases de datos que aloja su base de datos, y eso cambiará junto con la ejecución de su programa PL/SQL.

Este utiliza el Oracle directoryTMP_DIR; usted tiene que declarar, y crear el procedimiento siguiente:

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

Aquí es cómo usarlo:

1) Lanzamiento esto desde SQL * PLUS cliente:

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) en el servidor de base de datos, abrir un shell y

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