2011-09-08 14 views
6

Tengo un bloque PL/SQL que requiere bastante tiempo y que genera huellas digitales a partir de estructuras moleculares. Me gustaría imprimir la salida a la consola SQL * Plus para proporcionar retroalimentación sobre cuántas estructuras se han procesado. Puedo hacer esto con dbms_output.put_lineSupervisión del bloque PL/SQL de larga ejecución

Sin embargo, cada vez que se llama una nueva línea se escribe. Quiero sobrescribir la línea.

Por ejemplo, actualmente tengo el siguiente.

Structure x of y processed 
Structure x of y processed 
Structure x of y processed 
Structure x of y processed 

Eventualmente llené el búfer ya que estoy tratando con miles de registros de estructura.

¿Hay algún método que pueda usar que sobrescriba la última línea de salida?

Respuesta

15

El uso de DBMS_OUTPUT significa que SQL * Plus no mostrará nada hasta que se complete todo el bloque PL/SQL y luego mostrará todos los datos actualmente en el búfer. No es, por lo tanto, una forma apropiada de proporcionar un estado continuo.

Por otro lado, Oracle proporciona un paquete DBMS_APPLICATION_INFO que está específicamente diseñado para ayudarlo a controlar su código de ejecución. Por ejemplo, usted podría hacer algo como

CREATE PROCEDURE process_structures 
AS 
    <<other variable declarations>> 

    rindex BINARY_INTEGER; 
    slno  BINARY_INTEGER; 
    totalwork NUMBER := y; -- Total number of structures 
    worksofar NUMBER := 0; -- Number of structures processed 
BEGIN 
    rindex := dbms_application_info.set_session_longops_nohint; 

    FOR i IN (<<select structures to process>>) 
    LOOP 
    worksofar := worksofar + 1; 
    dbms_application_info.set_session_longops(
     rindex  => rindex, 
     slno  => slno, 
     op_name  => 'Processing of Molecular Structures', 
     sofar  => worksofar , 
     totalwork => totalwork, 
     target_desc => 'Some description', 
     units  => 'structures'); 
    <<process your structure with your existing code>> 
    END LOOP; 
END; 

Desde una sesión SQL * Plus separada, que puede progresar a continuación monitorizada consultando la vista V$SESSION_LONGOPS

SELECT opname, 
     target_desc, 
     sofar, 
     totalwork, 
     units, 
     elapsed_seconds, 
     time_remaining 
    FROM v$session_longops 
WHERE opname = 'Processing of Molecular Structures'; 
+1

+1, bonito ejemplo de plantilla. – DCookie

0

no creo que pueda. Por lo que yo entendí el dbms_output simplemente no funciona de esa manera.

Te recomiendo usar poner para repetir un solo punto y una nueva línea cada 1000 o más entradas para ver que algo está sucediendo y escribir en una tabla o secuenciar la posición actual para que puedas echar un vistazo si quieres saber.

1

También puede enviar mensajes a una tubería con nombre y tener otro proceso para leer el mensaje de la tubería.

procedure sendmessage(p_pipename varchar2 
         ,p_message varchar2) is 
     s number(15); 
    begin 
     begin 
     sys.dbms_pipe.pack_message(p_message); 
     exception 
     when others then 
      sys.dbms_pipe.reset_buffer; 
     end; 

     s := sys.dbms_pipe.send_message(p_pipename, 0); 

     if s = 1 
     then 
     sys.dbms_pipe.purge(p_pipename); 
     end if; 
    end; 


    function receivemessage(p_pipename varchar2 
          ,p_timeout integer) return varchar2 is 
     n number(15); 
     chr varchar2(200); 
    begin 
     n := sys.dbms_pipe.receive_message(p_pipename, p_timeout); 

     if n = 1 
     then 
     return null; 
     end if; 

     sys.dbms_pipe.unpack_message(chr); 
     return(chr); 
    end; 
Cuestiones relacionadas