est-il possible d'avoir des sorties de PL / SQL en temps réel? J'ai un paquet assez énorme qui fonctionne pendant plus d'une heure et j'aimerais voir où se trouve le colis à un moment donné. P>
Quoi qu'il en soit, je le fais actuellement avec une table en rondins, qui est remplie de centaines de descriptions de journaux par exécution, je suis juste curieux si cela est possible. P>
Merci! P>
6 Réponses :
Je ne sais pas si c'est exactement ce que vous voulez, mais j'utilise dbms_application_info.set_module pour voir où mon colis est. requête sur v $ session code> vous montrera quelle partie de la procédure est en cours d'exécution. P> p>
Vous pouvez utiliser Transactions autonomes (comme suggéré dans Cela est donc par exemple) . p>
Cela vous permettrait d'écrire et de vous engager dans une table de journaux sans que la transaction principale. Vous seriez alors en mesure de suivre ce qui se passe dans votre script principal lorsqu'il est en cours d'exécution (incidemment, cela vous permettra également de choisir votre lot). P>
+1 Il existe également une bonne description dans «Oracle Pl / SQLProgramming» de Feuerstein, qui est également disponible dans Google Books.
C'est le genre de chose que j'utilise (on peut voir la sortie dans V $ Session et V $ session_longops) ...
DECLARE lv_module_name VARCHAR2(48); lv_action_name VARCHAR2(32); gc_MODULE CONSTANT VARCHAR2(48) := 'MY_PROC'; -- For LONGOPS lv_rindex BINARY_INTEGER; lv_slno BINARY_INTEGER; lc_OP_NAME CONSTANT VARCHAR2(64) := '['||gc_MODULE||']'; lv_sofar NUMBER; -- This is a guess as to the amount of work we will do lv_totalwork NUMBER; lc_TARGET_DESC CONSTANT VARCHAR2(64) := 'Tables'; lc_UNITS CONSTANT VARCHAR2(64) := 'Rows'; CURSOR tab_cur IS SELECT owner, table_name FROM all_tables; BEGIN <<initialisation>> BEGIN -- To preserve the calling stack, read the current module and action DBMS_APPLICATION_INFO.READ_MODULE( module_name => lv_module_name , action_name => lv_action_name ); -- Set our current module and action DBMS_APPLICATION_INFO.SET_MODULE( module_name => gc_MODULE , action_name => NULL ); END initialisation; <<main>> BEGIN DBMS_APPLICATION_INFO.SET_ACTION( action_name => 'Part 01' ); NULL; DBMS_APPLICATION_INFO.SET_ACTION( action_name => 'Part 02' ); FOR tab_rec IN tab_cur LOOP DBMS_APPLICATION_INFO.SET_CLIENT_INFO( client_info => 'Rows = ['||TO_CHAR( tab_cur%ROWCOUNT, '999,999,999' )||']' ); NULL; END LOOP; DBMS_APPLICATION_INFO.SET_ACTION( action_name => 'Part 03' ); --Initialising longops lv_rindex := DBMS_APPLICATION_INFO.SET_SESSION_LONGOPS_NOHINT; lv_sofar := 0; lv_totalwork := 5000; -- This is a guess, but could be actual if the query is quick FOR tab_rec IN tab_cur LOOP DBMS_APPLICATION_INFO.SET_CLIENT_INFO( client_info => 'Rows = ['||TO_CHAR( tab_cur%ROWCOUNT, '999,999,999' )||']' ); lv_sofar := lv_sofar + 1; -- Update our totalwork guess IF lv_sofar > lv_totalwork THEN lv_totalwork := lv_totalwork + 500; END IF; DBMS_APPLICATION_INFO.SET_SESSION_LONGOPS( rindex => lv_rindex , slno => lv_slno , op_name => lc_OP_NAME , sofar => lv_sofar , totalwork => lv_totalwork , target_desc => lc_TARGET_DESC , units => lc_UNITS ); END LOOP; -- Clean up longops DBMS_APPLICATION_INFO.SET_SESSION_LONGOPS( rindex => lv_rindex , slno => lv_slno , op_name => lc_OP_NAME , sofar => lv_sofar , totalwork => lv_sofar , target_desc => lc_TARGET_DESC , units => lc_UNITS ); END main; <<finalisation>> BEGIN -- Reset the module and action to the values that may have called us DBMS_APPLICATION_INFO.SET_MODULE( module_name => lv_module_name , action_name => lv_action_name ); -- Clear the client info, preventing any inter process confusion for anyone looking at it DBMS_APPLICATION_INFO.SET_CLIENT_INFO( client_info => NULL ); END finalisation; END; /
Utilisez dbms_pipe pour écrire un message à un tuyau nommé. Dans une autre session, vous pouvez lire les messages du tuyau. Très simple, fonctionne comme un charme!
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;
Si votre travail de longue date traite un grand nombre de tâches de taille assez équitablement, vous trouverez peut-être une session Longops un bon moyen de surveiller les progrès de l'emploi, ainsi que de vous permettre d'estimer combien de temps le travail prendra à la fin. p>
Si vous avez accès à Shell à partir de l'environnement PL / SQL, vous pouvez appeler Netcat: P>
commencez run_shell ('echo "' '|| v_msg ||'" | nc '|| v_host ||' '|| v_port ||' -w 5 '); Fin; p>
/ p>
J'ai utilisé cette conception lorsque j'ai écrit aplogrez pour Shell et Surveillance des journaux PL / SQL. P> v_host code> est un script Python d'hôte qui lit les données de la prise sur le port
v_port code>. P>