1

ディスク読み取りが最も多いクエリに関するレポートを生成しようとしています。生成されたレポートは電子メールとして送信されます。私は以下のようにいくつかのコードを書きました。トップ15のクエリを含めると正常に機能しますが、カウントを増やすと「数値または値のエラー」が発生します。これは、一部のデータ型の制限を超えたが、それを識別できなかったために発生したと思います。誰かが問題を見ていますか?そして、どうすればこのようなエラーなしで巨大なレポートを送信できますか?

F_GENERATE_REPORT関数とP_SEND_REPORT_AS_EMAILプロシージャがあります。P_SEND_REPORT_AS_EMAILプロシージャは、UTL_MAIL.SEND(message => F_GENERATE_REPORT(5))のように電子メールの本文としてF_GENERATE_REPORTを使用します。ここで、5はtOP5に使用されます。

プロシージャP_SEND_REPORT_AS_EMAILのUTL_MAIL.SEND()行でエラーが発生しました

皆さんありがとう。

clgenerated_html_markupは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;

メール送信手順

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 => 'mehmet.altiparmak@domain.com',
               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;
4

2 に答える 2

5

UTL_MAIL.SENDの署名は次のとおりです。

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);

ご覧のとおり、このプロシージャmessageは、VARCHAR2ではなくCLOBを使用してパラメータを使用して呼び出しています。最大32kバイトの暗黙的な変換が開始され、すべてが正常に実行されます。発生しているエラーは、VARCHAR2(> 32kバイト)に変換できないCLOBを使用してプロシージャーにフィードしようとした場合に発生していると思われます。

OracleでCLOBメッセージを含む電子メールを送信する最も簡単な方法は、APEX_EMAILを使用することです(DBの最新バージョンにデフォルトでインストールされています。インストールされていない場合は、OracleからAPEXをダウンロードできます)。古いバージョンでは、いくつかの回避策が必要になります。たとえば、Tom Kyteは、 Javaを使用してAskTomのOracle8iで大きな電子メールを送信する方法について説明しています。または、独自のPLSQLプロシージャを記述したり、ネット上で調査を行ったりすることもできます。UTL_TCPを使用してメールサーバーと通信する(および選択した形式でデータを送信する)ことが可能であることがわかります。

于 2010-07-22T13:59:55.933 に答える
3

PL/SQLのVarchar2の最大サイズは32Kです。clgenerated_html_markupはclobを使用しているため、問題はありませんが、UTL_MAIL.SENDを呼び出すと、Varchar2に変換しようとしますが、変換できません。ここに示すように、UTL_SMTPなどの低レベルの電子メールツールに切り替える必要があります。

リンクを詳しく見てみると、それが最良の例かどうかはわかりませんが、UTL_SMTPを使用して送信するメッセージとしてclobを受け入れる手順の良い例は見つかりませんでした。概念は似ていますが、ヘッダーは次のようになります。

   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には、ここに構文の優れたリファレンスがあります。

于 2010-07-22T14:00:46.463 に答える