PL / SQL将查询结果分配给CLOB

我有一个问题,我创build一个CLOBvariables与oracle中的查询内容发送电子邮件给用户,问题是,它发送电子邮件为.csv,但没有内容。 我找不到问题:

CREATE OR REPLACE PROCEDURE trackekr(cursor1 IN OUT SYS_REFCURSOR) AS v_connection UTL_SMTP.connection; v_clob CLOB := EMPTY_CLOB(); v_len INTEGER; v_index INTEGER; c_mime_boundary CONSTANT VARCHAR2(256) := 'the boundary can be almost anything'; rec NUMBER(10, 0) := 0; d_id NUMBER(10, 0) := 0; customer VARCHAR2(20); wife VARCHAR2(20); date_rec DATE; special_h VARCHAR2(20); g_amount NUMBER(10, 0) := 0; credit_amount NUMBER(10, 0) := 0; a_number VARCHAR2(20); a__name VARCHAR2(20); BEGIN OPEN cursor1 FOR SELECT rec, d_id, customer, wife, date_rec, special h, g_amount FROM (your query here); WHILE cursor1%NOTFOUND LOOP FETCH cursor1 INTO rec, d_id, customer, wife, date_rec, special_h, g_amount, credit_amount, a_number, a__name; v_clob := v_clob || rec || ',' || d_id || ',' || customer || ',' || wife || ',' || date_rec || ',' || special_h || ',' || g_amount || ',' || credit_amount || ',' || a_number || ',' || a__name || UTL_TCP.crlf; END LOOP; -- UTL v_connection := UTL_SMTP.open_connection(mailhost, 25); SMTP server name or ip address UTL_SMTP.helo(v_connection, mail.exchange.mydomain.com); UTL_SMTP.mail(v_connection, 'mylogin.Exchange.mydomain.com'); UTL_SMTP.rcpt(v_connection, 'mylogin.Exchange.mydomain.com'); UTL_SMTP.open_data(v_connection); UTL_SMTP.write_data(v_connection, 'From: ' || 'mylogin.Exchange.mydomain.com' || UTL_TCP.crlf); UTL_SMTP.write_data(v_connection, 'To: ' || 'mylogin.Exchange.mydomain.com' || UTL_TCP.crlf); UTL_SMTP.write_data(v_connection, 'Subject: test subject' || UTL_TCP.crlf); UTL_SMTP.write_data(v_connection, 'MIME-Version: 1.0' || UTL_TCP.crlf); UTL_SMTP.write_data( v_connection, 'Content-Type: multipart/mixed; boundary="' || c_mime_boundary || '"' || UTL_TCP.crlf ); UTL_SMTP.write_data(v_connection, UTL_TCP.crlf); UTL_SMTP.write_data( v_connection, 'This is a multi-part message in MIME format.' || UTL_TCP.crlf ); UTL_SMTP.write_data(v_connection, '--' || c_mime_boundary || UTL_TCP.crlf); UTL_SMTP.write_data(v_connection, 'Content-Type: text/plain' || UTL_TCP.crlf); -- Set up attachment header UTL_SMTP.write_data( v_connection, 'Content-Disposition: attachment; filename="' || 'FIRSTFILE.csv' || '"' || UTL_TCP.crlf ); UTL_SMTP.write_data(v_connection, UTL_TCP.crlf); -- Write attachment contents v_len := DBMS_LOB.getlength(v_clob); v_index := 1; WHILE v_index <= v_len LOOP UTL_SMTP.write_data(v_connection, DBMS_LOB.SUBSTR(v_clob, 32000, v_index)); v_index := v_index + 32000; END LOOP; -- End attachment UTL_SMTP.write_data(v_connection, UTL_TCP.crlf); UTL_SMTP.write_data(v_connection, '--' || c_mime_boundary || '--' || UTL_TCP.crlf); UTL_SMTP.close_data(v_connection); UTL_SMTP.quit(v_connection); END; 

正如我所说,它发送电子邮件一个.csv文件,但空。

在你的代码中注意这个部分:

 WHILE cursor1%NOTFOUND 

您的循环永远不会执行非空数据集。 用这个代替:

 WHILE cursor1%FOUND 

或者更好的使用隐式游标:

 FOR cursor1 in (SELECT rec, d_id, customer, wife, date_rec, special_h, g_amount, credit_amount, a_number, a__name FROM (your query here)) LOOP v_clob := v_clob || cursor1.rec || ',' || cursor1.d_id || ',' || cursor1.customer || ',' || cursor1.wife || ',' || cursor1.date_rec || ',' || cursor1.special_h || ',' || cursor1.g_amount || ',' || cursor1.credit_amount || ',' || cursor1.a_number || ',' || cursor1.a__name || UTL_TCP.crlf; END LOOP; 

下面的例子,将查询写入clob,然后将blob写入文件

您只需要使用第一步,直到第87行

SELECT dbms_lob.getlength(l_clob)INTO len FROM dual;

 DECLARE l_output utl_file.file_type; c1 INTEGER DEFAULT dbms_sql.open_cursor; l_columnvalue VARCHAR2(4000); l_status INTEGER; l_colcnt NUMBER := 0; l_separator VARCHAR2(30); l_desctbl dbms_sql.desc_tab; l_flag NUMBER; l_dir VARCHAR2(50); l_arq VARCHAR2(100); l_clob CLOB; l_query VARCHAR2(50); vstart NUMBER := 1; bytelen NUMBER := 32000; len NUMBER; my_vr RAW(32000); x NUMBER; dest_offset INTEGER; src_offset INTEGER; blob_csid NUMBER; lang_context INTEGER; blb BLOB; warning INTEGER; BEGIN l_query := 'select * from safx07_v where rownum <=100'; SELECT 'safx07' || to_char(SYSDATE, 'DDMMYY_HH24MISS') || '.txt' INTO l_arq FROM dual; l_dir := 'ORACLE_EXP'; l_output := utl_file.fopen(l_dir, l_arq, 'wb'); --l_output := utl_file.fopen('ORACLE_EXP', 'filename.txt', 'wb', 32760); --l_separator := separator; IF l_separator = '' OR l_separator IS NULL THEN l_separator := chr(9); END IF; dbms_sql.parse(c1, l_query, dbms_sql.native); dbms_sql.describe_columns(c1, l_colcnt, l_desctbl); dbms_lob.createtemporary(l_clob, TRUE,DBMS_LOB.call); /* FOR cr IN (l_query) LOOP dbms_lob.writeappend(l_clob, length(cr.txt), cr.txt); END LOOP;*/ FOR i IN 1 .. l_colcnt LOOP dbms_output.put_line(l_desctbl(i).col_name || l_separator); dbms_output.put_line(length(l_desctbl(i).col_name || l_separator)); /* utl_file.put(l_output, l_desctbl(i).col_name || l_separator); dbms_sql.define_column(c1, i, l_columnvalue, 4000);*/ dbms_lob.writeappend(l_clob, length(l_desctbl(i).col_name || l_separator), l_desctbl(i).col_name || l_separator); dbms_sql.define_column(c1, i, l_columnvalue, 4000); END LOOP; --utl_file.new_line(l_output); l_status := dbms_sql.execute(c1); dbms_lob.writeappend(l_clob, length(chr(10)), chr(10)); WHILE (dbms_sql.fetch_rows(c1) > 0) LOOP FOR i IN 1 .. l_colcnt LOOP /* dbms_sql.column_value(c1, i, l_columnvalue); utl_file.put(l_output, l_columnvalue || l_separator);*/ dbms_sql.column_value(c1, i, l_columnvalue); dbms_lob.writeappend(l_clob, length(l_columnvalue || l_separator), l_columnvalue || l_separator); END LOOP; dbms_lob.writeappend(l_clob, length(chr(10)), chr(10)); END LOOP; --utl_file.fclose(l_output); SELECT dbms_lob.getlength(l_clob) INTO len FROM dual; dbms_lob.createtemporary(blb, FALSE); dest_offset := 1; src_offset := 1; lang_context := 0; -- convert to a BLOB here: dbms_lob.converttoblob(blb, l_clob, dbms_lob.getlength(l_clob), dest_offset, src_offset, 0, lang_context, warning); -- if small enough for a single write IF len < 32760 THEN utl_file.put_raw(l_output, blb); utl_file.fflush(l_output); ELSE -- write in pieces vstart := 1; WHILE vstart < len AND bytelen > 0 LOOP dbms_lob.read(blb, bytelen, vstart, my_vr); utl_file.put_raw(l_output, my_vr); utl_file.fflush(l_output); -- set the start position for the next cut vstart := vstart + bytelen; -- set the end position if less than 32000 bytes x := x - bytelen; IF x < 32000 THEN bytelen := x; END IF; END LOOP; END IF; dbms_sql.close_cursor(c1); utl_file.fclose(l_output); EXCEPTION WHEN OTHERS THEN dbms_sql.close_cursor(c1); utl_file.fclose(l_output); RAISE; END;