通过PL / SQL需要两个excel表单作为邮件的附件

我的要求是通过邮件发送来自Oracle表格的数据作为excel表格附件发送给客户。 我能够从一个表中获得一个Excel表格作为附件,但是我需要从两个表格中获取两个Excel表格。

DECLARE p_email VARCHAR2(255) ; p_subject VARCHAR2(255) := 'Weekly Report'; p_message CLOB; l_mailhost VARCHAR2(255) := 'mail.ABC.com'; l_mail_conn utl_smtp.connection; v_clob CLOB := EMPTY_CLOB(); v_len INTEGER; v_index INTEGER; s_clob CLOB := EMPTY_CLOB(); s_len INTEGER; s_index INTEGER; headerLines_v CLOB := EMPTY_CLOB(); headerLines_s CLOB := EMPTY_CLOB(); length_v INTEGER; length_s INTEGER; crlf VARCHAR2(2) := chr(13)||chr(10); v_date VARCHAR2(15) := TO_CHAR(TRUNC(SYSDATE),'DD_MM_YYYY'); CURSOR cur_a IS SELECT a, b, c FROM TABLE1 CURSOR cur_b IS SELECT x, y, z FROM TABLE2 BEGIN /*Table header in attachment*/ DBMS_LOB.CreateTemporary( v_clob, true ); headerLines_v := 'a,b,c'|| UTL_TCP.crlf; --// create CSV header line DBMS_LOB.WriteAppend( v_clob, length(headerLines_v), headerLines_v ); --// write it to CLOB DBMS_LOB.CreateTemporary( s_clob, true ); headerLines_s := 'x,y,z'|| UTL_TCP.crlf; --// create CSV header line DBMS_LOB.WriteAppend( s_clob, length(headerLines_s), headerLines_s ); --// write it to CLOB --// start loop to add data lines to CSV SELECT TO_CHAR(TRUNC(SYSDATE),'MM_DD_YYYY') INTO v_date FROM dual; --SELECT * INTO p_email FROM email WHERE module_name = 'REPORT'; p_message:= '<html> <BODY> <P> <font color="black",font face ="arial",font size ="2.5"> Hello All, <br/><br/> Please find the attachment for download details <br/> <br/>Thanks <br/> Application Team </P> </BODY> </html>'; l_mail_conn := utl_smtp.open_connection(l_mailhost, 25); utl_smtp.helo(l_mail_conn, l_mailhost); utl_smtp.mail(l_mail_conn, 'abc@yahoo.in'); utl_smtp.rcpt(l_mail_conn, 'abc@gmail.com'); utl_smtp.open_data(l_mail_conn ); utl_smtp.write_data(l_mail_conn, 'MIME-VERSION: 1.0' || crlf || 'FROM: ' || 'abc@yahoo.in' || crlf || 'Subject: '||'dowload status'||'['||v_date||']'|| crlf || 'TO: ' || 'abc@gmail.com'|| crlf || 'CONTENT-TYPE: multipart/mixed;' || crlf || ' boundary="---YOURBOUNDARY"' || crlf ||crlf); -- Email body utl_smtp.write_data(l_mail_conn, '-----YOURBOUNDARY'||crlf); utl_smtp.write_data(l_mail_conn, 'Content-Type: text/html' || crlf); utl_smtp.write_data(l_mail_conn, 'Content-Transfer-Encoding: 8bit' || crlf || crlf); utl_smtp.write_data(l_mail_conn, p_message||crlf); -- begin the attachment utl_smtp.write_data(l_mail_conn, '-----YOURBOUNDARY'||crlf); utl_smtp.write_data(l_mail_conn, 'Content-Type: text/plain;'||crlf); utl_smtp.write_data(l_mail_conn, 'Content-Transfer-Encoding: 8bit' || crlf); --utl_smtp.write_data(l_mail_conn, 'Mime-Type: application/zip' || crlf); utl_smtp.write_data(l_mail_conn, 'Content-Disposition: attachment;'|| crlf); utl_smtp.write_data(l_mail_conn, ' filename="Download_Data_1||.csv"'||crlf||crlf); UTL_SMTP.write_data(l_mail_conn, UTL_TCP.crlf); FOR rec IN cur_van LOOP v_clob := v_clob || a || ',' || b || ',' || c || UTL_TCP.crlf; END LOOP; v_len := DBMS_LOB.getlength(v_clob); v_index := 1; WHILE v_index <= v_len LOOP UTL_SMTP.write_data(l_mail_conn, DBMS_LOB.SUBSTR(v_clob, 32000, v_index)); v_index := v_index + 32000; END LOOP; UTL_SMTP.write_data(l_mail_conn, UTL_TCP.crlf); utl_smtp.close_data(l_mail_conn ); if DBMS_LOB.IsOpen( v_clob ) = 1 then DBMS_LOB.FreeTemporary( v_clob ); end if; -- begin the attachment utl_smtp.open_data(l_mail_conn ); utl_smtp.write_data(l_mail_conn, '-----YOURBOUNDARY'||crlf); utl_smtp.write_data(l_mail_conn, 'Content-Type: text/plain;'||crlf); utl_smtp.write_data(l_mail_conn, 'Content-Transfer-Encoding: 8bit' || crlf); --utl_smtp.write_data(l_mail_conn, 'Mime-Type: application/zip' || crlf); utl_smtp.write_data(l_mail_conn, 'Content-Disposition: attachment;'|| crlf); utl_smtp.write_data(l_mail_conn, ' filename="download_data_2||.csv"'||crlf||crlf); UTL_SMTP.write_data(l_mail_conn, UTL_TCP.crlf); FOR rec_2 IN cur_syn LOOP s_clob := s_clob || x || ',' || y || ',' || z || UTL_TCP.crlf; END LOOP; s_len := DBMS_LOB.getlength(s_clob); s_index := 1; WHILE s_index <= s_len LOOP UTL_SMTP.write_data(l_mail_conn, DBMS_LOB.SUBSTR(s_clob, 32000, s_index)); v_index := s_index + 32000; END LOOP; UTL_SMTP.WRITE_DATA(l_mail_conn, UTL_TCP.CRLF); utl_smtp.write_data(l_mail_conn, '-----YOURBOUNDARY'||crlf); UTL_SMTP.WRITE_DATA(l_mail_conn, UTL_TCP.CRLF || '.' || UTL_TCP.CRLF); if DBMS_LOB.IsOpen( s_clob ) = 1 then DBMS_LOB.FreeTemporary( s_clob ); end if; utl_smtp.close_data(l_mail_conn ); utl_smtp.quit(l_mail_conn); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE ('ERROR: '|| SQLCODE ||'Err Msg :'||SQLERRM); END; 

挣扎了很多之后,终于达到了上述要求。 代码是这样的:

 DECLARE v_from_name VARCHAR2(100) := 'abc@yahoo.in'; v_to_name VARCHAR2(100) := 'abc@gmail.com'; v_subject VARCHAR2(100); v_message_body CLOB; v_message_type VARCHAR2(100) := ' text/html'; v_smtp_server VARCHAR2(255) := 'mail.abc.com'; n_smtp_server_port NUMBER := 25; conn utl_smtp.connection; v_date VARCHAR2(15) := TO_CHAR(TRUNC(SYSDATE),'DD/MM/YYYY'); TYPE attach_info IS RECORD ( attach_name VARCHAR2(40), data_type VARCHAR2(40) DEFAULT 'text/plain', attach_content CLOB DEFAULT '' ); TYPE array_attachments IS TABLE OF attach_info; attachments array_attachments := array_attachments(); n_offset NUMBER; n_amount NUMBER := 1900; crlf VARCHAR2(5) := CHR(13) || CHR(10); v_clob CLOB := EMPTY_CLOB(); v_len INTEGER; v_index INTEGER; s_clob CLOB := EMPTY_CLOB(); s_len INTEGER; s_index INTEGER; c_mime_boundary CONSTANT VARCHAR2(256) := 'the boundary can be almost anything'; headerLines_v CLOB := EMPTY_CLOB(); headerLines_s CLOB := EMPTY_CLOB(); length_v INTEGER; length_s INTEGER; CURSOR cur_a IS SELECT a,b,c FROM Table1 where trunc(DATA_DATE) = TRUNC (SYSDATE); CURSOR cur_b IS SELECT x,y, z FROM Table2 WHERE TRUNC (CS_start_time) = TRUNC (SYSDATE); BEGIN DBMS_LOB.CreateTemporary( v_clob, true ); headerLines_v := 'a,b,c'|| UTL_TCP.crlf; --// create CSV header line DBMS_LOB.WriteAppend( v_clob, length(headerLines_v), headerLines_v ); --// write it FOR rec IN cur_a LOOP v_clob := v_clob || rec.ROWID || ',' ||a || ',' ||b || ',' ||c || UTL_TCP.crlf; END LOOP; DBMS_LOB.CreateTemporary( s_clob, true ); headerLines_s := ' x,y,z'|| UTL_TCP.crlf; --// create CSV header line DBMS_LOB.WriteAppend( s_clob, length(headerLines_s), headerLines_s ); --// write it to CLOB --// start loop to add data lines to CSV FOR rec_2 IN cur_b LOOP s_clob := s_clob || a || ',' || b || ',' ||c || UTL_TCP.crlf; END LOOP; -- Fill data for example attachments.extend(2); FOR i IN 1..2 LOOP SELECT 'File1'|| '.csv','text/plain',v_clob || to_char(1) INTO attachments(1) FROM dual; SELECT 'File2' || '.csv','text/plain',s_clob || to_char(2) INTO attachments(2) FROM dual; END LOOP; SELECT TO_CHAR(TRUNC(SYSDATE),'MM/DD/YYYY') INTO v_date FROM dual; --SELECT * INTO p_email FROM email WHERE module_name = 'REPORT'; v_message_body:= '<html> <BODY> <P> <font color="black",font face ="arial",font size ="2.5"> Hello All, <br/><br/> <br/> Please find the attachment for today's download details<br/> <br/>Thanks <br/>Application Team </P> </BODY> </html>'; -- Open the SMTP connection ... conn := utl_smtp.open_connection(v_smtp_server,n_smtp_server_port); utl_smtp.helo(conn, v_smtp_server); utl_smtp.mail(conn, v_from_name); utl_smtp.rcpt(conn, v_to_name); -- Open data utl_smtp.open_data(conn); -- Message info utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw('To: ' || v_to_name || crlf)); utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw('Date: ' || to_char(sysdate, 'Dy, DD Mon YYYY hh24:mi:ss') || crlf)); utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw('From: ' || v_from_name || crlf)); utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw('Subject: ' || 'Dowload status'||'['||v_date||']'||crlf)); utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw('MIME-Version: 1.0' || crlf)); utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw('Content-Type: multipart/mixed; boundary="SECBOUND"' || crlf || crlf)); -- Message body utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw('--SECBOUND' || crlf)); utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw('Content-Type: ' || v_message_type || crlf || crlf)); utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw(v_message_body || crlf)); -- Attachment Part FOR i IN attachments.FIRST .. attachments.LAST LOOP -- Attach info utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw('--SECBOUND' || crlf)); utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw('Content-Type: ' || attachments(i).data_type || ' name="'|| attachments(i).attach_name || '"' || crlf)); utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw('Content-Disposition: attachment; filename="' || attachments(i).attach_name || '"' || crlf || crlf)); -- Attach body n_offset := 1; WHILE n_offset < dbms_lob.getlength(attachments(i).attach_content) LOOP utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw(dbms_lob.substr(attachments(i).attach_content, n_amount, n_offset))); n_offset := n_offset + n_amount; END LOOP; utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw('' || crlf)); END LOOP; -- Last boundry utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw( '--SECBOUND' || crlf)); if DBMS_LOB.IsOpen( v_clob ) = 1 then DBMS_LOB.FreeTemporary( v_clob ); end if; if DBMS_LOB.IsOpen( s_clob ) = 1 then DBMS_LOB.FreeTemporary( s_clob ); end if; -- Close data utl_smtp.close_data(conn); utl_smtp.quit(conn); END;