oracle 的plussql语句导出查询结果,导出文件格式为csv格式
预备知识:
1. Oracle的存储过程知识
2. Oracle 的Utl_file,directory知识
3. 隐含知识点:plussql中表名用变量代替如何实现
假设要执行查询语句: select* from student; 这里想将student 用变量代理,那怎么处理呢?
定义一个变量 v_tablename
将student表名赋值给变量 v_tablename:=student
拼接sql语句: v_sql=’select * from ’||v_tablename;
执行sql语句:execute immediate v_sql;
所有代码块如下
declare
v_tablename varchar2(100);
v_sql varchar2(100);
begin
v_tablename:='student';
v_sql:='select * from '||v_tablename;
execute immediate v_sql;
end;
SQL_TO_CSV 存储过程
从网络上找来一个存储过程,实现了将查询结果导出生成csv文件,
存储过程代码如下
create or replace procedure outtocsv(P_QUERY IN VARCHAR2,P_DIRIN VARCHAR2,P_FILENAME IN VARCHAR2)
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-DDHH24: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 outtocsv;
上述存储过程 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:\下
declare
fhandleutl_file.file_type;
begin
sql_to_csv('select *from cus_event ','MYDIR','example.csv');
end;
【评论】上面是导出一个表,查询语句可以直接写,那么如果导出是多个表呢,那又该如果操作呢。既然是多个表,显然我们就要拼接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_tablenamevarchar2(100); -----用来存表名
v_sql varchar2(1000); -----用来存组合起来查询的sql语句
v_filenamevarchar2(100); ---用来存放构造的文件名
fhandleutl_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_foundthen ----直到文件末尾,即找不到数据了再停止
exit;
end ;
sql_to_csv(v_sql,'MYDIR',v_filename);----调用存储过程,将查询结果导出。这里核心部分
end loop;
end;