2010-07-22 8 views
1

J'essaie de générer un rapport sur les requêtes avec le plus de lectures de disque. Le rapport généré sera envoyé par e-mail. J'ai écrit du code comme ci-dessous. Lorsque j'inclus la requête du top 15, cela fonctionne bien mais si j'augmente le nombre de hte, j'obtiens 'erreur numérique ou valeur'. Je suppose que cela arrive parce que je dépasse certains types de données limite mais je ne pouvais pas l'identifier. Quelqu'un voit le problème? Et comment puis-je envoyer un rapport énorme sans une erreur comme celle-ci?ORACLE Erreur numérique ou de valeur

J'ai une fonction F_GENERATE_REPORT et une procédure P_SEND_REPORT_AS_EMAIL. procédure de P_SEND_REPORT_AS_EMAIL utilise F_GENERATE_REPORT que le corps de l'email comme UTL_MAIL.SEND (message => F_GENERATE_REPORT (5)) où 5 utilisé pour la page 5.

erreur a lieu sur la ligne UTL_MAIL.SEND() dans la procédure P_SEND_REPORT_AS_EMAIL

Merci à tous.

clgenerated_html_markup est une CLOB.

FOR cur_for_query IN (SELECT * 
         FROM (SELECT buffer_gets,rows_processed,executions, 
            fetches,hash_value,sql_text, disk_reads, 
            rank() over(ORDER BY disk_reads DESC) AS rank FROM v$sqlarea) 
         WHERE rank <= nquery_count) 
LOOP 
    --dbms_output.put_line(counter); 
    --counter := counter + 1; 
    clgenerated_html_markup := clgenerated_html_markup || HTF.TABLEROWOPEN || CHR(10) ; 
    clgenerated_html_markup := clgenerated_html_markup || HTF.TABLEDATA(cur_for_query.rank,null,null,null,null,null,'class=tdData') || CHR(10) ; 
    clgenerated_html_markup := clgenerated_html_markup || HTF.TABLEDATA(cur_for_query.sql_text,null,null,null,null,null,'class=tdSQLText') || CHR(10) ; 
    clgenerated_html_markup := clgenerated_html_markup || HTF.TABLEDATA(TO_CHAR(NVL(cur_for_query.disk_reads,'')),'CENTER',null,null,null,null,'class=tdData') || CHR(10) ; 
    clgenerated_html_markup := clgenerated_html_markup || HTF.TABLEDATA(TO_CHAR(NVL(cur_for_query.buffer_gets,'')),'CENTER',null,null,null,null,'class=tdData') || CHR(10) ; 
    clgenerated_html_markup := clgenerated_html_markup || HTF.TABLEDATA(TO_CHAR(NVL(cur_for_query.executions,'')),'CENTER',null,null,null,null,'class=tdData') || CHR(10) ; 
    clgenerated_html_markup := clgenerated_html_markup || HTF.TABLEDATA(TO_CHAR(NVL(cur_for_query.fetches,'')),'CENTER',null,null,null,null,'class=tdData') || CHR(10) ; 
    --clgenerated_html_markup := clgenerated_html_markup || HTF.TABLEDATA('','CENTER',null,null,null,null,'class=tdData') || CHR(10) ; 
    --clgenerated_html_markup := clgenerated_html_markup || HTF.TABLEDATA('','CENTER',null,null,null,null,'class=tdData') || CHR(10) ; 
    clgenerated_html_markup := clgenerated_html_markup || HTF.TABLEROWCLOSE || CHR(10) ; 
END LOOP; 

Envoyer un email Procédure

PROCEDURE P_SEND_REPORT_AS_EMAIL 
(
vreceipent VARCHAR2, 
vsubject VARCHAR2, 
nquery_count NUMBER DEFAULT 5 
) 

IS 
BEGIN 

-- INPUT VALIDATION 
IF vreceipent IS NULL THEN 
      RAISE_APPLICATION_ERROR(value_can_not_be_null,'DBA_EXHAUSTIVE_QUERY_PKG::P_SEND_REPORT_AS_EMAIL::Receipent Email Address Can Not Be Null.'); 
END IF; 
-- END OF INPUT VALIDATION 


UTL_MAIL.SEND(sender => '[email protected]', 
       recipients => vreceipent, 
       subject => NVL(vsubject,''), 
       message => F_GENERATE_REPORT(nquery_count), 
       mime_type => 'text/html; charset=us-ascii'); 

EXCEPTION 
WHEN OTHERS THEN 
    -- TODO LOG ERROR HERE 
RAISE; 

END P_SEND_REPORT_AS_EMAIL; 

Répondre

5

la signature pour UTL_MAIL.SEND est:

UTL_MAIL.SEND (
    sender  IN VARCHAR2 CHARACTER SET ANY_CS, 
    recipients IN VARCHAR2 CHARACTER SET ANY_CS, 
    cc   IN VARCHAR2 CHARACTER SET ANY_CS DEFAULT NULL, 
    bcc   IN VARCHAR2 CHARACTER SET ANY_CS DEFAULT NULL, 
    subject  IN VARCHAR2 CHARACTER SET ANY_CS DEFAULT NULL, 
** message  IN VARCHAR2 CHARACTER SET ANY_CS, ** 
    mime_type IN VARCHAR2 DEFAULT 'text/plain; charset=us-ascii', 
    priority IN PLS_INTEGER DEFAULT NULL); 

Comme vous pouvez le voir appeler cette procédure avec le paramètre message avec un CLOB au lieu d'un VARCHAR2. Jusqu'à 32k octets la conversion implicite entre en jeu et tout va bien. Je suppose que l'erreur que vous obtenez est lorsque vous essayez de nourrir la procédure avec un CLOB qui n'est pas convertible en VARCHAR2 (> 32k octets). Le moyen le plus simple d'envoyer des courriels avec des messages CLOB dans Oracle est de passer par APEX_EMAIL (installé par défaut sur les versions les plus récentes de la base de données, s'il n'est pas installé, vous pouvez télécharger APEX depuis Oracle). Sur les anciennes versions, vous auriez besoin d'une solution de contournement. Par exemple, Tom Kyte décrit comment use java to send large emails in Oracle 8i sur AskTom. Alternativement, vous pouvez également écrire votre propre procédure PLSQL ou faire des recherches sur le net, vous trouverez qu'il est possible d'utiliser UTL_TCP pour parler à un serveur de messagerie (et envoyer des données dans le format de votre choix).

+0

+1 APEX_Email est joli. Cela nous aurait fait gagner beaucoup de temps si nous étions disponibles lorsque nous avons roulé notre wrapper utl_smpt. –

3

La taille maximale d'un Varchar2 en PL/SQL est de 32K. Comme clgenerated_html_markup utilise un clob, vous y parvenez, mais lorsque vous appelez UTL_MAIL.SEND, il essaie de le convertir en Varchar2 et ne le peut pas. Vous devrez passer à un outil de messagerie de niveau inférieur tel que UTL_SMTP comme vu here. En regardant le lien plus, je ne suis pas sûr que c'est le meilleur exemple, mais je n'ai pas trouvé un bon exemple d'une procédure acceptant un clob comme le message à envoyer en utilisant UTL_SMTP. Le concept est similaire, mais votre tête devrait ressembler à quelque chose comme ceci:

PROCEDURE SendSMTP(
     pTo  Varchar2 Default null, 
     pSubject Varchar2 Default null, 
     pBody  Clob  Default empty_clob, 
     pFrom  Varchar2 Default null, 
     pCC  Varchar2 Default null, 
     pBCC  Varchar2 Default null, 
     pMimeType Varchar2 Default cDefaultMimeType, 
     pSMTPHost Varchar2 Default cDefaultMailServer, 
     pSMTPPort pls_integer Default cDefaultPort) 

Psoug.org a une bonne référence pour la syntaxe here.

Questions connexes