如何将选择查询的结果发送到oracle 10G中邮件的消息正文

Posted

技术标签:

【中文标题】如何将选择查询的结果发送到oracle 10G中邮件的消息正文【英文标题】:How to send the result of a select query to a message body of a mail in oracle 10G 【发布时间】:2013-08-13 07:20:28 【问题描述】:
CREATE OR REPLACE PROCEDURE STATUS_MAIL(FROM_MAIL IN VARCHAR2, TO_MAIL IN VARCHAR2)
is
  v_From      VARCHAR2(80) := FROM_MAIL;
  v_Recipient VARCHAR2(80) := TO_MAIL;
  v_Subject   VARCHAR2(80) := 'EMPLOYEE STATUS';
  v_Mail_Host VARCHAR2(30) := 'xx.xx.xxx.xxx';
  v_Mail_Conn utl_smtp.Connection;
  v_msg_body VARCHAR2(5000);
  v_output VARCHAR2(5000);

BEGIN 
 /*Result always returns 42 rows*/
 v_output := 'select empid,ename,mobile,dept from employee';
 EXECUTE IMMEDIATE v_output into v_msg_body;

 v_Mail_Conn := utl_smtp.Open_Connection(v_Mail_Host, xx);
 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') || UTL_TCP.crlf ||
   'From: '   || v_From || UTL_TCP.crlf ||
   'Subject: '|| v_Subject || UTL_TCP.crlf ||
   'To: '     || v_Recipient || UTL_TCP.crlf ||
   UTL_TCP.crlf || v_msg_body );
 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;

获取错误不一致的数据类型 @EXECUTE IMMEDIATE v_output 到 v_msg_body 在执行上述过程时,请帮助我....

【问题讨论】:

您想将employee 表中的所有记录发送到v_msg_body 变量中? 是的,上面的查询只返回 42 行,并且都必须传递给“v_msg_body”变量。 【参考方案1】:

所以实际上你真正的问题是:“如何将多行聚合成一个字符串?”

答案是使用aggregate functions。 Oracle 在 11gR2 中引入了listagg-function,很好地解决了这个问题,但在早期版本中,我们需要做更多的工作。

当您知道正确的关键字时,Google 会找到大量优质资源,例如

String Aggregation Techniques listagg function in 11g release 2 the collect function in 10g

我从上述资源中收集了以下示例。希望这能给您一个好的起点:

要查询的表:

create table foo (d1 number, d2 varchar2(10));
insert all
into foo values(1, 'a')
into foo values(2, 'b')
into foo values(3, 'c')
select 1 from dual;
commit;

Oracle 11gR2:

declare
  v_str varchar2(32767);
begin
  select listagg('key = ' || d1 || ' value = ' || d2, chr(10))
  within group (order by d1)
    into v_str
    from foo;

  dbms_output.put_line(v_str);
exception
  when value_error then
    dbms_output.put_line('Exception: trying to insert too many characters to a varchar2 variable.');
end;
/

Oracle 10g:

create or replace type str_list_t as table of varchar2(32676);
/

create function to_string (
  nt_in        in str_list_t,
  delimiter_in in varchar2 default ','
) return varchar2 is
  v_idx pls_integer;
  v_str varchar2(32767);
  v_dlm varchar2(10);
begin
  v_idx := nt_in.first;
  while v_idx is not null loop
    v_str := v_str || v_dlm || nt_in(v_idx);
    v_dlm := delimiter_in;
    v_idx := nt_in.next(v_idx);
  end loop;

  return v_str;
end;
/

declare
  v_str varchar2(32676);
begin
  select to_string(cast(collect('key = ' || d1 || ' value = ' || d2) as str_list_t), chr(10))
    into v_str
    from foo;
  dbms_output.put_line(v_str);
exception
  when value_error then
    dbms_output.put_line('Exception: trying to insert too many characters to a varchar2 variable.');
end;
/

请注意,如果聚合字符串不适合保留的 varchar2 容量,我将如何捕获将引发的 value_error 异常。

两个例子的输出:

key = 1 value = a
key = 2 value = b
key = 3 value = c

【讨论】:

以上是关于如何将选择查询的结果发送到oracle 10G中邮件的消息正文的主要内容,如果未能解决你的问题,请参考以下文章

如何连接具有选择性重复记录的表? (oracle10g)

oracle 10g 在查询结果列中添加rownum列,查询出的条数增多。

oracle 10g如何将列转换为行

Oracle Forms 10g 自动查询

oracle 10g中如何将多列查询成更多列

如何通过电子邮件发送 oracle 查询结果。我更喜欢以 excel 文件的形式附加到电子邮件中。