Oracle 查询结果导出为csv格式
目录
oracle 的plussql语句导出查询结果,导出文件格式为csv格式 | ||
预备知识:1. Oracle的存储过程知识 2. Oracle 的Utl_file,directory知识 3. 隐含知识点:plussql中表名用变量代替如何实现
| ||
SQL_TO_CSV 存储过程从网络上找来一个存储过程,实现了将查询结果导出生成csv文件, 存储过程代码如下 | ||
CREATE OR REPLACE PROCEDURE SQL_TO_CSV ( P_QUERY IN VARCHAR2, -- PLSQL文 P_DIR IN VARCHAR2, -- 导出的文件放置目录 P_FILENAME IN VARCHAR2 -- CSV名 ) IS L_OUTPUT UTL_FILE.FILE_TYPE; L_THECURSOR INTEGER DEFAULT DBMS_SQL.OPEN_CURSOR; L_COLUMNVALUE VARCHAR2(4000); L_STATUS INTEGER; L_COLCNT NUMBER := 0; L_SEPARATOR VARCHAR2(1); L_DESCTBL DBMS_SQL.DESC_TAB; P_MAX_LINESIZE NUMBER := 32000; BEGIN --OPEN FILE L_OUTPUT := UTL_FILE.FOPEN(P_DIR, P_FILENAME, ‘W’, P_MAX_LINESIZE);
--DEFINE DATE FORMAT EXECUTE IMMEDIATE ‘ALTER SESSION SET NLS_DATE_FORMAT=’’YYYY-MM-DD HH24:MI:SS’’’;
--OPEN CURSOR DBMS_SQL.PARSE( L_THECURSOR, P_QUERY, DBMS_SQL.NATIVE ); DBMS_SQL.DESCRIBE_COLUMNS( L_THECURSOR, L_COLCNT, L_DESCTBL );
--DUMP TABLE COLUMN NAME FOR I IN 1 .. L_COLCNT LOOP UTL_FILE.PUT( L_OUTPUT, L_SEPARATOR || ‘”’ || L_DESCTBL(I).COL_NAME || ‘”’ ); DBMS_SQL.DEFINE_COLUMN( L_THECURSOR, I, L_COLUMNVALUE, 4000 ); L_SEPARATOR := ‘,’; END LOOP; UTL_FILE.NEW_LINE( L_OUTPUT );
--EXECUTE THE QUERY STATEMENT L_STATUS := DBMS_SQL.EXECUTE(L_THECURSOR);
--DUMP TABLE COLUMN VALUE WHILE ( DBMS_SQL.FETCH_ROWS(L_THECURSOR) > 0 ) LOOP L_SEPARATOR := ‘’; FOR I IN 1 .. L_COLCNT LOOP DBMS_SQL.COLUMN_VALUE( L_THECURSOR, I, L_COLUMNVALUE ); UTL_FILE.PUT( L_OUTPUT, L_SEPARATOR || ‘”’ || TRIM(BOTH ‘ ‘ FROM REPLACE(L_COLUMNVALUE,’”’,’””’)) || ‘”’); L_SEPARATOR := ‘,’; END LOOP; UTL_FILE.NEW_LINE( L_OUTPUT ); END LOOP;
--CLOSE CURSOR DBMS_SQL.CLOSE_CURSOR(L_THECURSOR);
--CLOSE FILE UTL_FILE.FCLOSE( L_OUTPUT ); EXCEPTION WHEN OTHERS THEN RAISE; END; | ||
上述存储过程 SQL_TO_CSV 需要了解oracle中的utl_fiel、directory 的知识 下面调用 SQL_TO_CSV 存储过程的 前提就是定义一个directory, 定义语句如下: create or replace directory MYDIR as 'c:\'; | ||
一个表的查询结果导出 | ||
下面就开始调用 存储过程 SQL_TO_CSV,将 select * from cus_event 的查询结果,导出为example.csv并放在MYDIR所代表的C:\下
| ||
【评论】上面是导出一个表,查询语句可以直接写,那么如果导出是多个表呢,那又该如果操作呢。既然是多个表,显然我们就要拼接sql语句,是sql语句动态变化,且导出的文件名也要动态变化。有两种方案,一将表名放在数组中,逐个调用;二是将表名放在文件中,逐个读取 | ||
方案一:用数组存放表名从数组中取出表名,拼接sql语句,构造导出的csv文件名 | ||
declare v_tablename varchar2(100); -----用来存表名 v_sql varchar2(1000); -----用来存组合起来查询的sql语句 type my_email is varray(200) of varchar2(40);--定义数组 tables_arr my_email;--定义一个数组变量 v_filename varchar2(100); ---用来存放构造的文件名 begin tables_arr:=my_email('cus_grp_info','cus_event');-- 给数组变量赋值
for i in 1..2 loop dbms_output.put_line(tables_arr(i)); v_tablename:=tables_arr(i); v_sql:='select * from '||v_tablename; -----构造查询的sql语句 dbms_output.put_line(v_sql); v_filename:=v_tablename||'.csv'; -----构造查询导出后的文件名 dbms_output.put_line(v_filename); sql_to_csv(v_sql,'MYDIR',v_filename); ----调用存储过程,将查询结果导出 这里是核心部分 end loop; end; | ||
【评论】上述方案简单,但必须将表名手动放入数组中,例子中只到处两个表cus_grp_info,cus_event,但如果我们这里有上百张表,显然这种方法不太方便。我们通过会将表名存放在文件中。执行时从文件中读取表名,这样再多的表我们也能操作,且表的内容还可以随时方便的改变 | ||
方案二:用文件存表名从文件中取出表名,拼接sql语句,构造导出的csv文件名 | ||
declare v_tablename varchar2(100); -----用来存表名 v_sql varchar2(1000); -----用来存组合起来查询的sql语句 v_filename varchar2(100); ---用来存放构造的文件名 fhandle utl_file.file_type; -- 文件句柄 begin fhandle:=utl_file.fopen('MYDIR','tablelist.txt','r'); --获得tablelist的文件句柄 ---这里tablelist.txt 就存放中将要查询的表的表名,txt文件放在MYDIR代表的c:\ 目录下 loop begin utl_file.get_line(fhandle,v_tablename); ---从文件中一条一条读取表名,并存放在v_tablename中 dbms_output.put_line(v_tablename); v_sql:='select * from '||v_tablename; ---拼接查询语句 dbms_output.put_line(v_sql) ; v_filename:=v_tablename||'.csv'; ---构造导出的csv文件名 dbms_output.put_line(v_filename); exception when no_data_found then ----直到文件末尾,即找不到数据了再停止 exit; end ; sql_to_csv(v_sql,'MYDIR',v_filename); ----调用存储过程,将查询结果导出。这里核心部分 end loop; end; | ||
|
评论