? ?最近項目上有位同事遇到這樣一個問題
? ?在PLSQL中用UTL_FILE的包寫文件時,由于一行的數(shù)據(jù)過大(超過Vachar2的定義長度32k,也就是32767byte)報錯,來求助幫忙想辦法解決。(出力的文件是個CSV文件,第一行為行頭,后面是數(shù)據(jù),行頭里都是日語項目名,每個項目名有特別特別多和長)
? ? ?剛開始想到,既然是Vachar2的定義長度的限制,能不能把行頭分成2行輸出,然后輸出文件后再把2行行頭合并呢,因為這次是一個工具的程序,在plsql中寫出CSV文件,然后之后會用VBA程序讀入文件內(nèi)容到Excel的模板里。
? ? ?所以想到PLSQL輸出文件時先把出2行,再在VBA里合并就好了,可是經(jīng)過調(diào)查發(fā)現(xiàn)因為工具太過復雜,如果這個做需要大量的改動工作量。
? ?后來突然想到既然是Vachar2的定義長度的限制,能不能把頭行內(nèi)容改成CLOB類型輸出到一行再輸出數(shù)據(jù)呢,試驗了下這樣改動可以減少大量的工具改造。做法如下:
DECLARE
? l_directory VARCHAR2(20) := 'u01/path';--這里是文件輸出路徑
? l_file_name VARCHAR2(20) := 'test.csv';--這里是文件輸出文件
? l_file? ? ? utl_file.file_type;
? l_clob? CLOB;--原來出錯時用的是VARCHAR2(32767)
? l_len? ? ? BINARY_INTEGER?;
? l_pos BINARY_INTEGER?;
? l_buffer VARCHAR2(32767);
? l_amount BINARY_INTEGER ;
BEGIN
l_pos :=?1;
l_amount? :=?1024;
--此循環(huán)只是為了模擬超過32k長的行頭,放入l_clob 變量里。
FOR i IN 1 .. 5000
? LOOP
? ? l_clob := l_clob || '[共通]20kV?30kV力率修正前基本料金';
? END LOOP;
--此處是為了輸出行頭后換行
l_clob := l_clob||CHR(13)||CHR(10);
--select??dbms_lob.getlength(l_clob) into?l_len? from dual;
l_len := dbms_lob.getlength(l_clob);
? --此處不用W方式用WB
? l_file := utl_file.fopen(l_directory, l_file_name, 'wb', 32767);
? WHILE l_pos < l_len LOOP
? ? dbms_lob.READ(l_clob, l_amount, l_pos, l_buffer);
? ? utl_file.put_raw(l_file, utl_raw.cast_to_raw(l_buffer));
? ? utl_file.fflush(l_file);
? ? l_pos := l_pos + l_amount;
? END LOOP;
? utl_file.fclose(l_file);
EXCEPTION
? WHEN OTHERS THEN
? ? dbms_output.put_line(SQLERRM);
END;
/