1
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 into v_msg_body, 助けてください....

4

1 に答える 1

3

実際、あなたの本当の質問は次のとおりです。「複数の行を単一の文字列に集約するにはどうすればよいですか?」

答えは、集計関数を使用することです。Oracle はlistagg11gR2 で -function を導入してこの問題をうまく解決しましたが、以前のリリースではもう少し作業が必要でした。

適切なキーワードを知っていれば、Google は多くの優れたリソースを見つけます。

上記のリソースから次の例を収集しました。これが良い出発点になることを願っています:

クエリされるテーブル:

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;

オラクル 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;
/

オラクル 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;
/

集約された文字列が予約容量value_errorに収まらない場合に発生する例外をキャッチする方法に注意してください。varchar2

両方の例の出力:

key = 1 value = a
key = 2 value = b
key = 3 value = c
于 2013-08-13T11:45:39.090 に答える