使用PL / SQL proc将包含CLOB的转储表转换为csv

时间:2017-09-12 12:37:30

标签: oracle plsql

我已经组装了一个过程,将包含CLOB列的查询转储到csv文件中。 它似乎工作正常,直到我遇到包含日期的查询。

  

ORA-00932:不一致的数据类型:预期CLOB得到DATE

有没有办法将这些日期动态转换为某种默认字符串格式,以便能够像现在一样使用该过程。或者,如果有必要,我该如何重构呢?

create or replace
PROCEDURE export_query_csv(
      p_query     IN VARCHAR2,
      p_filename  IN VARCHAR2)
IS      
    l_separator   VARCHAR2 (10 CHAR) := ';';
    l_dir         VARCHAR2 (128 CHAR)  := 'MY_DIR';
    l_output      utl_file.file_type;
    l_theCursor   INTEGER DEFAULT dbms_sql.open_cursor;
    l_columnValue CLOB;
    l_status      INTEGER;
    l_colCnt      NUMBER DEFAULT 0;
    l_cnt         NUMBER DEFAULT 0;
    l_descTbl     dbms_sql.desc_tab; 

    l_substrVal VARCHAR2(4000) ;
    l_offset NUMBER :=1;
    l_amount NUMBER := 3000;
    l_clobLen NUMBER :=0;
  BEGIN
    EXECUTE IMMEDIATE 'alter session set nls_date_format = ''dd-mon-yyyy hh24:mi:ss''';

    l_output := utl_file.fopen(l_dir, p_filename, 'wb');

    dbms_sql.parse(l_theCursor, p_query, dbms_sql.native);

    FOR i IN 1 .. 1000
    LOOP
      BEGIN
        dbms_sql.define_column(l_theCursor, i, l_columnValue);
        l_colCnt := i;
      EXCEPTION
      WHEN OTHERS THEN
        IF ( SQLCODE = -1007 ) THEN
          EXIT;
        ELSE
          RAISE;
        END IF;
      END;
    END LOOP;

    dbms_sql.describe_columns( l_theCursor, l_colCnt, l_descTbl ); 

    FOR i IN 1 .. l_colCnt 
    LOOP
      utl_file.put_raw(l_output,utl_raw.cast_to_raw('"'));
      utl_file.put_raw(l_output,utl_raw.cast_to_raw(l_descTbl(i).col_name));
      utl_file.put_raw(l_output,utl_raw.cast_to_raw('"'));
      IF i < l_colCnt THEN
        utl_file.put_raw(l_output,utl_raw.cast_to_raw(l_separator));
      END IF;
    END LOOP;

    utl_file.put_raw(l_output,utl_raw.cast_to_raw(chr(13) || chr(10)));

    l_status := dbms_sql.execute(l_theCursor);
    LOOP
      EXIT WHEN (dbms_sql.fetch_rows(l_theCursor) <= 0);
      FOR i IN 1 .. l_colCnt
      LOOP
        dbms_sql.column_value(l_theCursor, i, l_columnValue);

        l_clobLen := dbms_lob.getlength(l_columnValue);
        WHILE l_offset <= l_clobLen
        LOOP
          l_substrVal := dbms_lob.substr(l_columnValue,l_amount,l_offset);
          utl_file.put_raw(l_output,utl_raw.cast_to_raw('"'));
          utl_file.put_raw(l_output,utl_raw.cast_to_raw(l_substrVal));
          utl_file.put_raw(l_output,utl_raw.cast_to_raw('"'));
          l_offset:=l_offset+l_amount;
        END LOOP;
        l_offset := 1;

        IF i < l_colCnt THEN
          utl_file.put_raw(l_output,utl_raw.cast_to_raw(l_separator));
        END IF;
      END LOOP;
      utl_file.put_raw(l_output,utl_raw.cast_to_raw(chr(13) || chr(10)));
      l_cnt := l_cnt + 1;
    END LOOP;

    dbms_sql.close_cursor(l_theCursor);
    utl_file.fclose(l_output);

END;

1 个答案:

答案 0 :(得分:2)

按照这种模式自己找到它:

-- Define columns
FOR i IN 1 .. colcnt LOOP
    IF desctab(i).col_type = 2 THEN
       DBMS_SQL.DEFINE_COLUMN(curid, i, numvar);
    ELSIF desctab(i).col_type = 12 THEN
        DBMS_SQL.DEFINE_COLUMN(curid, i, datevar);
......
     ELSE
        DBMS_SQL.DEFINE_COLUMN(curid, i, namevar);
     END IF;
END LOOP;
相关问题