之前经常用plsql执行脚本,将查出来的数据以.csv的格式导出然后提交给客户。由于近期的清单数量增加,每份清单的数据量也比较大,所以再用plsql提取就非常耗时。因为大部分清单的脚本是固定的,所以想着是否可以使用存储过程定时执行脚本直接导出清单。于是,就开始各种百度查阅资料,终于成功实现了不用手动执行脚本就可以导出清单的好方法。

实现方法都在下面存储过程的注释里,其中第二部分:PRC_DATA_TO_CSV存储过程会调用第一部分:PRC_SQL_TO_CSV 存储过程实现数据以.csv格式导出的导出。

第一部分:

CREATE OR REPLACE PROCEDURE PRC_SQL_TO_CSV
                                      (P_QUERY IN VARCHAR2,    -- 查询语句
                                       P_DIR IN VARCHAR2,      -- 导出的文件放置目录/只能是应用服务器上的路径
                                       P_FILENAME IN VARCHAR2  -- 文件名.csv格式/输出的csv文件
                                       )
/******************************************************************************
  * 功能名称:以CSV的格式导出表数据
  * 功能描述:
  * @Description:
  * @Copyright: FFCS(C) 2017
  * @Company: FFCS
  * @author Wang Yiren
  * @Version 0.1.1 date:2018年02月27日
  *******************************************************************************/
/*
第一步:修改数据库utl_file_dir参数,命令如下:
             show parameter utl_file_dir;--查看参数
             alter system set utl_file_dir = '/oradata/ftp/' scope = spfile;  --修改参数,参数为linux服务器相关路径
第二步:重启数据库,使修改的参数生效
第三步:定义一个directory,命令如下:
             create or replace directory MYDIR as '/oradata/ftp/';
第四部:测试
 declare
begin
  PRC_SQL_TO_CSV('select * from view_LDAPM_MPW_BD_PSNDOC t where t.MONTH_ID = 201712','MYDIR','LDAPM_MPW_BD_PSNDOC.csv');
end;
 */
 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;


第二部分:



CREATE OR REPLACE PROCEDURE PRC_DATA_TO_CSV AUTHID CURRENT_USER IS
/******************************************************************************
  * 功能名称:多张表数据以CSV格式导出
  * 功能描述:
  * @Description:
  * @Copyright: FFCS(C) 2017
  * @Company: FFCS
  * @author Wang Yiren
  * @Version 0.0.1 date:2018年02月27日
  *******************************************************************************/
/*
 * 使用方法:此存储过程与PRC_SQL_TO_CSV配合使用,
 * 其中要在 MYDIR 代表的/oradata/ftp/ 目录下
 * 新建一个tablelist.tex文件,此文件是需要导出数据的表名
 */
v_tablename VARCHAR2(100);   --用来存表名
v_sql VARCHAR2(1000);        --用来存组合起来查询的sql语句
v_filename VARCHAR2(100);    --用来存放构造的文件名

--v_realName  VARCHAR2(100);    -- 用来存放汉字的表名

--V_DAY_MONTH_ID VARCHAR2(10); --日账期
V_MONTH_MONTH_ID VARCHAR2(8);--月账期

fhandle utl_file.file_type;   -- 文件句柄

BEGIN
  --获取日账期
   V_SQL := 'select to_char(sysdate,''yyyymm'') from dual';
  EXECUTE IMMEDIATE V_SQL
    INTO V_MONTH_MONTH_ID;
    
  V_MONTH_MONTH_ID := 201802; 
    
    --DBMS_OUTPUT.PUT_LINE(V_DAY_MONTH_ID);
  --获得tablelist的文件句柄---这里tablelist.txt 就存放中将要查询的表的表名,txt文件放在MYDIR代表的/oradata/ftp/目录下  
  fhandle := utl_file.fopen('MYDIR','tablelist.txt','r');
  LOOP
    BEGIN
      utl_file.get_line(fhandle,v_tablename);---从文件中一条一条读取表名,并存放在v_tablename中
      dbms_output.put_line(v_tablename);
      v_sql := 'select * from '||v_tablename||' t where t.month_id = '||V_MONTH_MONTH_ID; ---拼接查询语句
      dbms_output.put_line(v_sql);
      
      
      --select table_desc into v_realName from tab2bean_corresref  where table_view = v_tablename;
      
      v_filename := V_MONTH_MONTH_ID||'_'||v_tablename||'.csv';---构造导出的csv文件名:201803_VIEW_DATALIST_BD_PSNDOC.csv
      
      dbms_output.put_line(v_filename);
      EXCEPTION
      WHEN no_data_found then ----直到文件末尾,即找不到数据了再停止
        EXIT;
        END;
     PRC_SQL_TO_CSV(v_sql,'MYDIR',v_filename);----调用存储过程,将查询结果导出。这里核心部分
     END LOOP;
END;