Campo maior que long

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
Kleito Cesar
Rank: Estagiário Sênior
Rank: Estagiário Sênior
Mensagens: 13
Registrado em: Ter, 28 Out 2008 9:32 pm
Localização: SC

Boa tarde pessoal,

Tenho uma procedure que gera um HTML dinamico e outra procedure que envia email.

Porém em alguns casos o HTML se torna enorme(ele já está bem customizado), que na hora que estou gerando este HTML armazeno em um campo do tipo LONG e quando chega em um certo ponto este campo estoura.

Alguém sabe me dizer se tem algum outro campo maior que LONG e que eu possa manipular string's, ou alguma outra solução?

Obrigado
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

LONG é coisa do "arco da véia"... Só existe ainda pra fins de compatibilidade com versões antigas.

As "coisas da modernidade" são campos do tipo BLOB ou CLOB... Outra leitura importante é sobre a DBMS_LOB !! :-D
Kleito Cesar
Rank: Estagiário Sênior
Rank: Estagiário Sênior
Mensagens: 13
Registrado em: Ter, 28 Out 2008 9:32 pm
Localização: SC

Obrigado dr_gori.

E qual destes seria mais interessante para este caso?
Trevisolli
Moderador
Moderador
Mensagens: 2016
Registrado em: Qua, 12 Jan 2005 3:25 pm
Localização: Araraquara - SP
Abraço,

Trevisolli
OCA Oracle PL/SQL Developer Certified Associate
OCP Oracle Forms Developer Certified Professional
Araraquara-SP

Brother, se for só texto, poderia armazenar num Clob mesmo.
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

Isso!
CLOB é pra texto
BLOB é pra binário
Kleito Cesar
Rank: Estagiário Sênior
Rank: Estagiário Sênior
Mensagens: 13
Registrado em: Ter, 28 Out 2008 9:32 pm
Localização: SC

Bom..
O que fiz foi só trocar a declaração do campo de long para CLOB.

E ela faz a manipulação direitinho sem aparentar erros, até a chamada da procedure que envia o email.

Chamada da procedure:

Selecionar tudo

        BEGIN GDOC_PRC_ENVIA_EMAIL('email', 'GS/Documents', C1.DS_EMAIL,'[GS/Documents] Relatório semanal de apontamentos', campoCLOB);END;
A procedure

Selecionar tudo


PROMPT CREATE OR REPLACE PROCEDURE gdoc_prc_envia_email
CREATE OR REPLACE PROCEDURE gdoc_prc_envia_email( P_REMETENTE IN VARCHAR2,
                                                  P_NOME_REMETENTE IN VARCHAR2,
                                                  P_DESTINATARIO IN VARCHAR2,
                                                  P_ASSUNTO IN VARCHAR2,
                                                  P_MENSAGEM   IN CLOB
                                                  ) IS

/* P_ORIGEM   - Email de quem está enviando                   P_REMETENTE
   P_DESTINO  - Email de quem vai receber
   P_ASSUNTO  - Assunto do email
   P_TEXTO    - Texto do email */

  MAILHOST VARCHAR2(30) := 'xxx'; -- NOME OU IP DO SERVIDOR SMTP
  MAILPORT NUMBER(4)    :=25;           -- PORTA SMTP
  MAIL_CONN UTL_SMTP.CONNECTION;
  WDS_USER VARCHAR2(30)    :=  'usuario';
  WDS_PASSWORD VARCHAR2(9) := 'senha';
  CRLF VARCHAR2(2)         := CHR(13)||CHR(10);


 BEGIN
        MAIL_CONN:= utl_smtp.open_connection(MAILHOST, MAILPORT);
        utl_smtp.helo(MAIL_CONN,  MAILHOST);
        utl_smtp.command (MAIL_CONN,  'AUTH LOGIN');
        utl_smtp.command (MAIL_CONN,  utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw((WDS_USER )))));
        utl_smtp.command (MAIL_CONN,  utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw((WDS_PASSWORD)))));   --> senha

        UTL_SMTP.MAIL (MAIL_CONN,  ('<' || P_REMETENTE || '>')); /* E-mail de quem está mandando */
        UTL_SMTP.RCPT (MAIL_CONN,  ('<' || P_DESTINATARIO|| '>')); /* Para quem vou mandar */
        --
        utl_smtp.open_data(MAIL_CONN);
        UTL_SMTP.WRITE_RAW_DATA( MAIL_CONN, UTL_RAW.CAST_TO_RAW('From:'    ||P_NOME_REMETENTE||'<'|| P_REMETENTE|| '>' || utl_tcp.CRLF));
        UTL_SMTP.WRITE_RAW_DATA( MAIL_CONN, UTL_RAW.CAST_TO_RAW('To:'      ||P_DESTINATARIO||utl_tcp.CRLF));
        UTL_SMTP.WRITE_RAW_DATA( MAIL_CONN, UTL_RAW.CAST_TO_RAW('Subject:' ||P_ASSUNTO||utl_tcp.CRLF));
        UTL_SMTP.WRITE_RAW_DATA( MAIL_CONN, UTL_RAW.CAST_TO_RAW('Content-Type: text/html; charset=iso-8859-1'||utl_tcp.CRLF));
        --
        utl_smtp.write_data(MAIL_CONN, ' '||utl_tcp.CRLF);

        utl_smtp.write_raw_data(MAIL_CONN, utl_raw.cast_to_raw(utl_tcp.CRLF||P_MENSAGEM));
        --
        UTL_SMTP.CLOSE_DATA(MAIL_CONN);
        UTL_SMTP.QUIT (MAIL_CONN);
  EXCEPTION
    WHEN OTHERS THEN
        UTL_SMTP.QUIT (MAIL_CONN);
        --
END;
/
O erro:

Selecionar tudo

ORA-29277: operação SMTP inválida
ORA-06512: em "SYS.UTL_SMTP", line 43
ORA-06512: em "SYS.UTL_SMTP", line 149
ORA-06512: em "SYS.UTL_SMTP", line 358
ORA-06512: em "SYS.UTL_SMTP", line 374
ORA-06512: em "GEDOC_DESENV.GDOC_PRC_ENVIA_EMAIL", line 45
ORA-06502: PL/SQL: erro numérico ou de valor
ORA-06512: em "GEDOC_DESENV.GDOC_ENVIA_EMAIL_APONTAMENTO", line 294
ORA-06512: em line 1
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

O que é exatamente esta linha 45 no seu código?

Selecionar tudo

ORA-06512: em "GEDOC_DESENV.GDOC_PRC_ENVIA_EMAIL", line 45
ORA-06502: PL/SQL: erro numérico ou de valor 
Kleito Cesar
Rank: Estagiário Sênior
Rank: Estagiário Sênior
Mensagens: 13
Registrado em: Ter, 28 Out 2008 9:32 pm
Localização: SC

é bem no exception da procedure.

Se eu comentar a exceção o erro vai acontecer na seguinte linha:


Selecionar tudo

        utl_smtp.write_raw_data(MAIL_CONN, utl_raw.cast_to_raw(P_MENSAGEM));
Obs. P_MENSAGEM é o campo CLOB.
Trevisolli
Moderador
Moderador
Mensagens: 2016
Registrado em: Qua, 12 Jan 2005 3:25 pm
Localização: Araraquara - SP
Abraço,

Trevisolli
OCA Oracle PL/SQL Developer Certified Associate
OCP Oracle Forms Developer Certified Professional
Araraquara-SP

Brother,

Tenta desta forma:

Selecionar tudo

      utl_smtp.write_data(MAIL_CONN, P_MENSAGEM); 
Kleito Cesar
Rank: Estagiário Sênior
Rank: Estagiário Sênior
Mensagens: 13
Registrado em: Ter, 28 Out 2008 9:32 pm
Localização: SC

Acontece este erro ao executar a procedure:

PLS-00306: número incorreto de tipos de argumentos na chamada para 'WRITE_RAW_DATA'

Isto deve ser porque ele não aceita o tipo CLOB como parametro.
Trevisolli
Moderador
Moderador
Mensagens: 2016
Registrado em: Qua, 12 Jan 2005 3:25 pm
Localização: Araraquara - SP
Abraço,

Trevisolli
OCA Oracle PL/SQL Developer Certified Associate
OCP Oracle Forms Developer Certified Professional
Araraquara-SP

Brother,

Tenta somente o WRITE_DATA, ao invés do WRITE_RAW_DATA:

Selecionar tudo

  utl_smtp.write_data(MAIL_CONN, P_MENSAGEM); 
Kleito Cesar
Rank: Estagiário Sênior
Rank: Estagiário Sênior
Mensagens: 13
Registrado em: Ter, 28 Out 2008 9:32 pm
Localização: SC

Continua dando o mesmo erro de antes dai..

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

Mas eu reparei o seguinte:
Como falei antes este erro acontece em determinadas situações onde o texto se estende muito, mas com o tipo do campo CLOB não dá problema na hora da manipulação do texto, aparentemente ele está correto, o problema acontece somente quando o campo é passado de parametro para o utl_smtp e o campo CLOB é muito extenso.

Então creio que provavelmente é o UTL_SMTP que não está aguentando os dados.

Isto faz sentido?
Tem alguma saída?

Obrigado.
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

O TOM KYTE fez um exemplo onde ele envia os dados pra UTL_SMPT de 1900 em 1900 bytes.
Veja:
link

Outro exemplo:
http://forums.oracle.com/forums/thread. ... 8&tstart=0
Kleito Cesar
Rank: Estagiário Sênior
Rank: Estagiário Sênior
Mensagens: 13
Registrado em: Ter, 28 Out 2008 9:32 pm
Localização: SC

\o/ Funcionou.
Obrigado pessoal.

Eu resolvi eliminar a procedure de envio de email, e adicionar o texto particionado para o UTL_SMTP.

Valeu.
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 basicamente o mesmo problema do nosso amigo que criou esse post. 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;
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

Lembra que o DBMS_OUTPUT.PUT_LINE só suporta 255 caracteres.
Mais que isso dá erro.
Veja: http://asktom.oracle.com/pls/asktom/f?p ... 6412348066

Será que não está dando outro erro antes desse ? (e o exception ta gerando um outro).
rsampaio
Rank: Estagiário Sênior
Rank: Estagiário Sênior
Mensagens: 9
Registrado em: Qua, 07 Ago 2013 4:02 pm

Gori,

Eu não estou utilizando o DBMS nesse procedimento, eu fiz somente um teste para saber se o problema era com a procedure de envio de email.

Em relação ao erro mascarado pelo Exception, eu também acho que não é, porque eu tirei o exception do procedimento e ele retornou o mesmo erro.
mih_cns
Rank: Estagiário Pleno
Rank: Estagiário Pleno
Mensagens: 6
Registrado em: Qui, 25 Jun 2015 11:06 am

olá estou passando por um problema parecido.
Estou querendo enviar um e-mail com anexo, porem o anexo só sai o html.
O resultado do select mesmo não sai.
alguém ajuda?

Selecionar tudo

     -- Envia o e-mail 

     DECLARE
   v_From       VARCHAR2(80) := V_E_MAIL_ORIGEM;
   v_Recipient  VARCHAR2(80) := V_E_MAIL_DESTINO;
   v_Subject    VARCHAR2(200) := V_E_MAIL_ASSUNTO_1;
   v_Mail_Host  VARCHAR2(30) := 'smtp-appl1.senado.gov.br';
   v_Mail_Conn  utl_smtp.Connection;
   crlf         VARCHAR2(2)  := chr(13)||chr(10);
   
BEGIN
  v_Mail_Conn := utl_smtp.Open_Connection(v_Mail_Host, 25);

  utl_smtp.Helo(v_Mail_Conn, v_Mail_Host);

  utl_smtp.Mail(v_Mail_Conn, v_From);

  utl_smtp.Rcpt(v_Mail_Conn, v_Recipient);

  utl_smtp.Data(v_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 ||
    'some message text'|| crlf ||   -- Message body
    'more message text'|| crlf ||
    crlf ||

    '-------SECBOUND'|| crlf ||
    'Content-Type: text/plain;'|| crlf ||
    ' name="excel.csv"'|| crlf ||
    'Content-Transfer_Encoding: 8bit'|| crlf ||
    'Content-Disposition: attachment;'|| crlf ||
    ' filename="excel.csv"' || crlf ||
    crlf ||
    V_TEXTO_EMAIL|| crlf ||   -- Content of attachment
    crlf ||

    '-------SECBOUND--'         -- End MIME mail
  );

  utl_smtp.Quit(v_mail_conn);
EXCEPTION
  WHEN utl_smtp.Transient_Error OR utl_smtp.Permanent_Error then
    raise_application_error(-20000, 'Unable to send mail: '||sqlerrm);
END;
               
               
maxwbh
Rank: Estagiário Sênior
Rank: Estagiário Sênior
Mensagens: 10
Registrado em: Ter, 21 Out 2014 5:16 pm
Localização: Belo Horizonte - MG
Maxwell da Silva Oliveira
(31) 9325.7479/ 9474.8854
maxwbh@gmail.com
http://lnkd.in/PkcQ5y

O erro ocorre por que você deve particionar o campo BLOB.
veja no exemplo :

Selecionar tudo

        v_length := dbms_lob.getlength(p_attach_blob);
        <<while_loop>>
        WHILE v_offset < v_length LOOP
            dbms_lob.read(p_attach_blob, l_step, v_offset, v_raw);
            utl_smtp.write_raw_data(vconexao, utl_encode.base64_encode(v_raw));
            utl_smtp.write_data(vconexao, utl_tcp.crlf);
            v_offset := v_offset + l_step;
        END LOOP while_loop;
O Código completo esta em :
https://github.com/Maxwbh/SendMail/
Responder
  • Informação
  • Quem está online

    Usuários navegando neste fórum: Majestic-12 [Bot] e 12 visitantes