ORA-06502: PL/SQL: erro numérico ou de valor

Dúvidas, dicas e truques de PL/SQL. Aqui também vão assuntos relacionados a pacotes, triggers, funções, Java-Stored Procedures, etc
Responder
rsampaio
Rank: Estagiário Sênior
Rank: Estagiário Sênior
Mensagens: 9
Registrado em: Qua, 07 Ago 2013 4:02 pm

Pessoal, boa tarde.

Estou com um problema em um procedimento que armazena informações de texto e depois envia por email em um arquivo em anexo. O intuito do procedimento que eu fiz é: a partir do conteúdo de uma consulta em uma view, vou incluindo linha a linha em uma variável do tipo CLOB e depois, preciso enviar esse conteúdo em um email com o arquivo(txt) em anexo.

Tudo isso que eu disse acima está funcionando, porém, com uma restrição. A consulta original retorna 150 linhas, mas se eu deixar assim, aparece o erro: ORA-06502: PL/SQL: erro numérico ou de valor.

Se eu limitar o resultado da consulta em 50 linhas, todo o procedimento funciona perfeitamente.
O erro aparece se eu utilizar a rotina de envio de email e aparece também se eu usar um simples DBMS_OUTPUT.PUT_LINE.

O conteúdo desse arquivo txt tem mais ou menos, em cada linha, 600 caracteres.
Será que alguém consegue me dar uma mão? Segue abaixo o procedimento:

Selecionar tudo

DECLARE
   TYPE V_CONTEUDO_ARRAY IS TABLE OF CLOB;

   V_CONTEUDO   V_CONTEUDO_ARRAY;
   V_ARQUIVO    CLOB;
   V_STATUS     INTEGER;
   V_LINHA      LONG;
   V_TESTE      BOOLEAN;
   NOME_ARQUIVO VARCHAR2(50);

   CURSOR CONTEUDO IS
      SELECT CONTEUDO
        FROM VW_INTEGRACAO_GOVRJ
       WHERE ROWNUM <= 50
       ORDER BY ORDEM;

BEGIN

   OPEN CONTEUDO;
   FETCH CONTEUDO BULK COLLECT
      INTO V_CONTEUDO;
   CLOSE CONTEUDO;

   V_TESTE := TRUE;
   DBMS_OUTPUT.ENABLE(NULL);

   FOR I IN 1 .. V_CONTEUDO.COUNT LOOP
      IF V_TESTE = TRUE THEN
         V_ARQUIVO := V_CONTEUDO(I);
         V_TESTE   := FALSE;
         V_STATUS  := V_CONTEUDO.COUNT;
      ELSE
         V_ARQUIVO := V_ARQUIVO || CHR(13) || CHR(10) || V_CONTEUDO(I);
      END IF;
   END LOOP;

   SEND_MAIL(V_FROM              => 'xxxxxx',
             V_RECIPIENT         => 'yyyyyy',
             V_SUBJECT           => 'assunto teste',
             V_BODY              => 'conteudo teste',
             V_NOME_ARQUIVO      => NOME_ARQUIVO, 
             V_CONTEUDO_ARQUIVO  => V_ARQUIVO);

EXCEPTION
   WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE('Exception, Quantidde de Linhas = ' || V_STATUS);
      DBMS_OUTPUT.PUT_LINE(SQLERRM);
      DBMS_OUTPUT.PUT_LINE(V_LINHA);
END;
rsampaio
Rank: Estagiário Sênior
Rank: Estagiário Sênior
Mensagens: 9
Registrado em: Qua, 07 Ago 2013 4:02 pm

Segue abaixo uma linha de exemplo do arquivo:

Selecionar tudo

20679     A12S042417     CLIENTE XX                                        SOARES DE MIRANDA                                           00000                         BAIRRO1                       292234920001660000285000029500000000100000000015000000000042,87000000000042,87000000000000,00000000000000000000000000000,00000000000000,40000000000000,00000000000086,14130525130400                                                                      00000127296120000000000000000000000000000000000000000000000000000000000000000000 0000000000 0000000000 0000000000 0000000000 0000000000 00000000129041330031308130000000000000000,00
wmendes.miranda
Rank: Estagiário Sênior
Rank: Estagiário Sênior
Mensagens: 11
Registrado em: Qui, 26 Ago 2010 10:51 am
Localização: São Paulo
Contato:
Quer aprender PL/SQL de graça? acesse http://aprendaplsql.com/ /*EM CONTRUÇÃO*/

Oi rsampaio, tudo bem?

O erro "ORA-06502: PL/SQL: erro numérico ou de valor." aparece muitas vezes quando o problema acontece dentro de uma function/procedure que esta sendo chamada por outra que possui o SQLERRM no tratamento de erros, uma dica que eu te dou para descobrir o real problema é você tirar essa EXCEPTION no final do código. Vai dar um erro sem tratamento, mas será o erro real.

Quanto ao problema no DBMS_OUTPUT pode ser com a versão do seu banco de dados, de acordo com essa documentação da Oracle http://docs.oracle.com/cd/B19306_01/app ... tm#i999293, quando você usa o NULL no

Selecionar tudo

DBMS_OUTPUT.ENABLE(NULL);
dependendo da sua versão do banco de dados ele seta com default o limite 20000, porque algumas versão não aceitam buffer ilimitado. ("NULL is expected to be the usual choice. The default is 20,000 for backwards compatibility with earlier database versions that did not support unlimited buffering.").

Você tem uma média de 600 e 150 registros se você definir um buffer de 90000 acredito que o seu problema será solucionado, se ele não for de uma olhada no SEND_MAIL, se quiser envia o código desse procedimento, assim conseguimos te ajudar mais.

abs e espero ter ajudado.
William Miranda
rsampaio
Rank: Estagiário Sênior
Rank: Estagiário Sênior
Mensagens: 9
Registrado em: Qua, 07 Ago 2013 4:02 pm

Willian, obrigado pelo comentário.

Mas na verdade o erro que ocorre é esse mesmo: Erro numérico ou de valor. Esse tratamento de erro eu coloquei depois que tive esse problema. Até tirei novamente para testar o que você disso, mas o erro continua o mesmo.

Outra coisa também é que não importa a forma que vou utilizar o campo que vai receber o conteúdo do arquivo, ele sempre da esse erro. Usando a procedure de email ou o DBMS, o erro é o mesmo.

Não sei mais o que fazer....
rsampaio
Rank: Estagiário Sênior
Rank: Estagiário Sênior
Mensagens: 9
Registrado em: Qua, 07 Ago 2013 4:02 pm

Alguém tem alguma luz? :(
Avatar do usuário
dr_gori
Moderador
Moderador
Mensagens: 5024
Registrado em: Seg, 03 Mai 2004 3:08 pm
Localização: Portland, OR USA
Contato:
Thomas F. G

Você já respondeu a dúvida de alguém hoje?
https://glufke.net/oracle/search.php?search_id=unanswered

Acho que a gente teria que ver como que essa SEND_MAIL ta enviando emails.
Talvez tenha algum problema ali (as vezes o 'content-type: text/html;' pode estar errado, etc)
rsampaio
Rank: Estagiário Sênior
Rank: Estagiário Sênior
Mensagens: 9
Registrado em: Qua, 07 Ago 2013 4:02 pm

Segue abaixo o código da procedure SEND_MAIL.

Selecionar tudo

CREATE OR REPLACE PROCEDURE SEND_MAIL(V_FROM             IN VARCHAR2,
                                      V_RECIPIENT        IN VARCHAR2,
                                      V_SUBJECT          IN VARCHAR2,
                                      V_MAIL_HOST        IN VARCHAR2 DEFAULT,
                                      V_SMTP_PORT        IN NUMBER DEFAULT 25,
                                      V_BODY             IN VARCHAR2,
                                      V_NOME_ARQUIVO     IN VARCHAR2,
                                      V_CONTEUDO_ARQUIVO IN CLOB) IS

   L_MAIL_CONN UTL_SMTP.CONNECTION;
   CRLF        VARCHAR2(2) := CHR(13) || CHR(10);

BEGIN

   L_MAIL_CONN := UTL_SMTP.OPEN_CONNECTION(V_MAIL_HOST, V_SMTP_PORT);
   UTL_SMTP.HELO(L_MAIL_CONN, V_MAIL_HOST);
   UTL_SMTP.MAIL(L_MAIL_CONN, V_FROM);
   UTL_SMTP.RCPT(L_MAIL_CONN, V_RECIPIENT);

   IF (LENGTH(V_NOME_ARQUIVO) > 0) THEN
      UTL_SMTP.DATA(L_MAIL_CONN,
                    'Date: ' || TO_CHAR(SYSDATE, 'Dy, DD Mon YYYY hh24:mi:ss') || CRLF ||
                     'From: ' || V_FROM || CRLF || 'Subject: ' || V_SUBJECT || CRLF ||
                     'To: ' || V_RECIPIENT || CRLF ||
                    
                     'MIME-Version: 1.0' || CRLF || -- Use MIME mail standard
                     'Content-Type: multipart/mixed;' || CRLF ||
                     ' boundary="-----SECBOUND"' || CRLF || CRLF ||
                    
                     '-------SECBOUND' || CRLF || 'Content-Type: text/plain;' || CRLF ||
                     'Content-Transfer_Encoding: 7bit' || CRLF || CRLF || V_BODY || CRLF || -- Message body
                    --'more message text' || CRLF || CRLF ||
                     '-------SECBOUND' || CRLF || 'Content-Type: text/plain;' || CRLF ||
                     ' name="' || V_NOME_ARQUIVO || '"' || CRLF ||
                     'Content-Transfer_Encoding: 8bit' || CRLF ||
                     'Content-Disposition: attachment;' || CRLF || ' filename="' ||
                     V_NOME_ARQUIVO || '"' || CRLF || CRLF || V_CONTEUDO_ARQUIVO || CRLF || -- Content of attachment
                     CRLF ||
                    
                     '-------SECBOUND--'
                    -- End MIME mail
                    );
   ELSE
      UTL_SMTP.DATA(L_MAIL_CONN,
                    'Date: ' || TO_CHAR(SYSDATE, 'Dy, DD Mon YYYY hh24:mi:ss') || CRLF ||
                     'From: ' || V_FROM || CRLF || 'Subject: ' || V_SUBJECT || CRLF ||
                     'To: ' || V_RECIPIENT || CRLF ||
                    
                     'MIME-Version: 1.0' || CRLF || -- Use MIME mail standard
                     'Content-Type: multipart/mixed;' || CRLF ||
                     ' boundary="-----SECBOUND"' || CRLF || CRLF ||
                    
                     '-------SECBOUND' || CRLF || 'Content-Type: text/plain;' || CRLF ||
                     'Content-Transfer_Encoding: 7bit' || CRLF || CRLF || V_BODY || CRLF -- Message body
                    );
   END IF;
   UTL_SMTP.QUIT(L_MAIL_CONN);
EXCEPTION
   WHEN UTL_SMTP.TRANSIENT_ERROR OR UTL_SMTP.PERMANENT_ERROR THEN
      RAISE_APPLICATION_ERROR(-20000, 'Unable to send mail: ' || SQLERRM);
   
END SEND_MAIL;
Avatar do usuário
stcoutinho
Moderador
Moderador
Mensagens: 850
Registrado em: Qua, 11 Mai 2011 5:15 pm
Localização: são Paulo - SP

Rsampaio,

Tudo bem?

Talvez o erro que você esteja se deparando esteja diretamente relacionado com a quantidade de caracteres inseridos no seu campo CLOB.

Não sei se ajuda, mas tente fazer um teste com este exemplo do site do ORACLE-BASE:

http://www.oracle-base.com/articles/mis ... -plsql.php

O artigo acima parece estar bem completo e explica de forma bem didática os métodos para envio e email. Tem inclusive exemplos de e-mails com CLOB como anexo.

O autor do artigo é o britânico TIM HALL, que por coincidência foi um dos palestrantes do GUOB TECH DAY deste ano.


Abraços e boa sorte,

Sergio Coutinho
rsampaio
Rank: Estagiário Sênior
Rank: Estagiário Sênior
Mensagens: 9
Registrado em: Qua, 07 Ago 2013 4:02 pm

Fala Sergio, obrigado pelo seu comentário cara, mas o maldito erro continua! rs
Rodei o meu procedimento aqui com a procedure dele de envio de email e deu a mesma coisa.

Eu tenho quase certeza que o problema não é com o DBMS_OUTPUT e nem com a procedure de envio de email.
Tem algum outro problema que não deixa que essa variável CLOB fique grande.

Alguma configuração do Oracle pra tamanho de variável sei lá... não sei mais o que fazer.
Avatar do usuário
fbifabio
Moderador
Moderador
Mensagens: 199
Registrado em: Ter, 22 Fev 2011 1:51 pm
Localização: São Paulo - SP
Contato:
Fábio Prado
www.fabioprado.net

Rodrigo,

você já tentou usar a package que compartilho no artigo http://www.fabioprado.net/2013/01/envia ... -de_9.html?

Eu dei uma olhada rápida no seu código e não encontrei o erro. Tente identificar em qual linha do código está ocorrendo o erro para sabermos se o problema está na procedure que envia o e-mail ou no código em que você preenche a var clob do anexo, ok?
Avatar do usuário
fbifabio
Moderador
Moderador
Mensagens: 199
Registrado em: Ter, 22 Fev 2011 1:51 pm
Localização: São Paulo - SP
Contato:
Fábio Prado
www.fabioprado.net

Acho que já matei a charada.

Se V_ARQUIVO é do tipo CLOB, você não pode usar TO_CHAR ao atribuir valores para ela. você tem que usar TO_CLOB. Quando você faz TO_CHAR(V_ARQUIVO) e o tamanho dela passa 32767 (limite do VARCHAR2), você verá o erro.

Substitua:

Selecionar tudo

V_ARQUIVO := TO_CHAR(V_ARQUIVO) || CHR(13) || CHR(10) || TO_CHAR(V_CONTEUDO(I));
Por:

Selecionar tudo

V_ARQUIVO := V_ARQUIVO || TO_CLOB(CHR(13) || CHR(10)) || TO_CLOB(V_CONTEUDO(I));
Teste e me dê um retorno.

[]S
rsampaio
Rank: Estagiário Sênior
Rank: Estagiário Sênior
Mensagens: 9
Registrado em: Qua, 07 Ago 2013 4:02 pm

Fábio, perfeito cara! Não sabia que existia esse TO_CLOB!
Muito obrigado pela ajuda!

Grande Abraço.
Responder
  • Informação
  • Quem está online

    Usuários navegando neste fórum: Nenhum usuário registrado e 23 visitantes