ORACLE数字或值错误

时间:2010-07-22 13:04:28

标签: oracle numeric

我正在尝试生成有关磁盘读取次数最多的查询的报告。生成的报告将作为电子邮件发送。我写了一些代码如下。 当我包括前15个查询它工作正常但如果我增加hte计数我得到'数字或值错误'。我想这是因为我超过了某些数据类型的限制 但无法辨认出来。有人看到了这个问题吗?如何在没有这样的错误的情况下发送大量报告?

我有一个F_GENERATE_REPORT函数和P_SEND_REPORT_AS_EMAIL过程。 P_SEND_REPORT_AS_EMAIL过程使用F_GENERATE_REPORT作为正文 像UTL_MAIL.SEND(message => F_GENERATE_REPORT(5))这样的电子邮件,其中5用于第5页。

程序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;

2 个答案:

答案 0 :(得分: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);

正如您所看到的,使用带有CLOB而不是VARCHAR2的参数message调用此过程。最多32k字节隐式转换开始,一切都很好。我怀疑你得到的错误是当你试图用一个不能转换为VARCHAR2(> 32k字节)的CLOB来提供程序时。

在Oracle中发送带有CLOB消息的电子邮件的最简单方法是APEX_EMAIL(默认安装在最新版本的数据库上,如果没有安装,可以从Oracle下载APEX)。在旧版本上,您需要一些解决方法。例如,Tom Kyte描述了如何在AskTom上use java to send large emails in Oracle 8i。或者,您也可以编写自己的PLSQL程序或在网上进行一些研究,您会发现可以使用UTL_TCP与邮件服务器通信(并以您选择的格式发送数据)。

答案 1 :(得分:3)

PL / SQL中Varchar2的最大大小为32K。由于clgenerated_html_markup正在使用clob,你在那里很好,但是当你调用UTL_MAIL.SEND时,它试图将它转换为Varchar2而不能。您必须切换到较低级别的电子邮件工具,例如UTL_SMTP,如here所示。

再看一下这个链接,我不确定它是最好的例子,但我还没有找到一个接受clob作为使用UTL_SMTP发送消息的过程的好例子。这个概念是类似的,但你的标题应该看起来像这样:

   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对语法here提供了很好的参考。