Oracle PL/SQL - dicas para saída imediata/impressão do console
-
19-09-2019 - |
Pergunta
Eu tenho vários procedimentos pl/sql que podem levar vários minutos para serem executados.Ao desenvolvê-los, adicionei algumas instruções de impressão para ajudar na depuração e também fornecer alguns comentários e indicadores de progresso.Inicialmente, executei-os em pequenos conjuntos de testes e o resultado foi quase instantâneo.Agora que estou testando conjuntos de testes maiores que levam vários minutos para serem executados, descobri que imprimir no console não é mais adequado, porque nada é impresso até que o procedimento termine.Estou acostumado a trabalhar em ambientes que não armazenam em buffer sua saída e a imprimem imediatamente, e é comum adicionar instruções de impressão simples para depuração e diagnóstico simples.
É possível em pl/sql imprimir a saída imediatamente (sem buffer)?Caso contrário, que alternativas as pessoas recomendam para obter um resultado semelhante?
Solução
Você pode ter um procedimento que grava mensagens em uma tabela usando uma transação autônoma algo como:
procedure log (p_message)
is
pragma autonomous_transaction;
begin
insert into message_log (user, datetime, message)
values (user, sysdate, p_message);
commit;
end;
Em seguida, monitore a tabela de outra sessão do Oracle.
Outras dicas
temos um pequeno truque para isso.
você pode usar DBMS_APPLICATION_INFO.set_client_info("algumas informações aqui");criando algumas variáveis e substituindo a string dentro de " ".
e use select client_info from v$session para monitorar o progresso.
Eu tenho usado dbms_pipe para esse fim. Envie mensagens para um tubo nomeado e leia -as de outra sessão. Esse método pode não funcionar em um ambiente RAC quando os processos de redação e leitura podem se conectar a um nó diferente.
Como alternativa, você pode inserir mensagens em uma tabela usando um procedimento executado em sua própria sessão usando "Pragma Autonomous_transaction". Você pode consultar essas mensagens de outra sessão
EDIT: Vejo que minha segunda opção já foi mencionada.
Geralmente existem duas opções:
- Envie a saída para uma tabela Oracle (ou tabela temporária)
- Escreva no sistema de arquivos (host de banco de dados) com utl_file
Se você não tiver acesso ao SO ao host do banco de dados, ainda poderá gravar no sistema de arquivos DBHOST e vincular uma tabela definida externamente do Oracle ao arquivo para que ele possa ser consultado com uma seleção.
Pode depender da sua ferramenta cliente. Não usei o SQL*Plus há algum tempo, mas quando estou depurando procedimentos no desenvolvedor PL/SQL, abro uma janela de comando e emito um SET SERVEROUTPUT ON
comando. Então, quando eu executo o procedimento, qualquer coisa impressa por DBMS_OUTPUT.PUT_LINE
aparece imediatamente.
EDIT: Você está certo, acho que só estava vendo isso com quantidades maiores de saída ou algo assim. De qualquer forma, eu fiz algumas pesquisas online e me deparei com isso log4plsql - pode ser útil.
Uma alternativa é usar uma função de pipeline que retorne suas informações de registro. Veja aqui um exemplo: http://berxblog.blogspot.com/2009/01/pipelined-function-vs-dbmsoutput.html Quando você usa uma função de pipeline, não precisa usar outra sessão SQLPlus/Toad/SQL etc ....
Você pode usar o tubo DBMS e o visualizador de tubos no desenvolvedor PL/SQL para capturar de maneira assíncrona todos os Infos à medida que são colocados no tubo.
Tenha cuidado para colocar apenas as coisas em um cano quando houver alguém para lê -lo. Caso contrário, sua chamada falhará quando o tubo estiver cheio.
Há também a possibilidade de usar eventos, o desenvolvedor PL/SQL também possui um monitor de eventos. E os documentos devem fornecer um exemplo de como fazê -lo.
Outra opção é fazer com que seu PL/SQL ligue para um procedimento para enviar um email com a mensagem de log nele. Isso exige que seu banco de dados tenha um recurso de envio de email, que pode ser adicionado usando o UTL_SMTP.