0

我想就执行以下提到的场景的最佳方法获得一些意见。我只是在这里寻找一种替代的最佳方法,而不是调试错误。

我有一个 select 语句,它产生大约 150K 行和大约 10 列。我需要使用制表符分隔符连接列,然后循环遍历每一行并将所有内容组合成一行。此列值正在使用函数调用并从 UI 下载。

当前方法:编写一个流水线函数以将其作为 clob 输出并使用它从 UI 下载。

TYPE OUT_REC_CSV_TYP IS  RECORD
    ( object_status                    VARCHAR2        ( 4000    ) ,
     extract_csv                    CLOB    ) ;

TYPE OUT_REC_CSV_TABTYP IS TABLE OF OUT_REC_CSV_TYP;

FUNCTION GET_CSV_EXTRACT (P_DATE_REPORTED   IN VARCHAR2,
                          P__USER_ID        IN NUMBER DEFAULT NULL)
    RETURN OUT_REC_CSV_TABTYP
    PIPELINED
IS
    V_OUT_REC         OUT_REC_CSV_TYP;
    V_OUT_REC_EMPTY   OUT_REC_CSV_TYP;
BEGIN
    V_OUT_REC := V_OUT_REC_EMPTY;
    V_OUT_REC.OBJECT_STATUS := NULL;                         --- ADDING HEADER

    SELECT 'COLUMN_A' || CHR (9) || 'COLUMN_B'     AS extract_csv --have around 15 columns
      INTO V_OUT_REC.extract_csv
      FROM DUAL;

    FOR i IN (SELECT 'COLUMN_A' || CHR (9) || 'COLUMN_B'     AS extract_csv
                FROM (WITH
                          TABLE_A AS (SELECT * FROM table_1),
                          TABLE_B AS (SELECT * FROM table_2)
                      SELECT COLUMN_A, COLUMN_B
                        FROM TABLE_A, TABLE_B
                       WHERE TABLE_A.COLUMN_NAME = TABLE_B.COLUMN_NAME))
    LOOP
        V_OUT_REC.extract_csv :=
            V_OUT_REC.extract_csv || CHR (10) || i.extract_csv;
    END LOOP;

    PIPE ROW (V_OUT_REC);
    RETURN;
END GET_CSV_EXTRACT;

select extract_csv from TABLE(PACKAGE_NAME.GET_CSV_EXTRACT('04/19/2021','1'));

我可能用词不当。预期输出:所有行合并为一个由新行分隔的行 COL_A COL_B COL_C COL_D COL_E 155189 TEST TEST TEST ABCD 127557 TEST TEST TEST ABCD ....... 说大约 150K 行合并

这种方法有时会引发错误,并在几次尝试下载此 clob 值文本文件后起作用。

4

1 回答 1

0

(150K 行)*(10 列)在一行中?你是这么说的吗?谁能理解那里写的内容(请注意 TAB 作为列分隔符,以及可能的 NULL 值)。

另一方面,您发布的代码看起来像是每一行都在自己的行中;这个:

V_OUT_REC.extract_csv := V_OUT_REC.extract_csv || CHR (10) || i.extract_csv;

我可能错了,但我会说你的话与你的代码不匹配。


因此,另一种方法呢?SQL*Plus 及其spool命令。像这样的东西:

SQL> set linesize 100
SQL> set pagesize 0
SQL> set colsep "       "    --> this is (double quotes) (pressed TAB on keyboard) (double quotes)
SQL> spool test.txt
SQL> select * from dept;
        10      ACCOUNTING      NEW YORK
        20      RESEARCH        DALLAS
        30      SALES           CHICAGO
        40      OPERATIONS      BOSTON

SQL> spool off;

就如此容易。


或者,如果它必须是一个存储过程,我宁愿考虑UTL_FILE创建文件。但是,这种方法需要访问目录(通常位于数据库服务器上)。

SQL> declare
  2    l_handle  utl_file.file_type;
  3    l_delim   varchar2(20) := chr(9);   -- TAB character
  4  begin
  5    l_handle := utl_file.fopen('EXT_DIR',
  6                               'test.txt',
  7                               'w');
  8
  9    for cur_r in (select deptno, dname, loc
 10                  from dept)
 11    loop
 12      utl_file.put_line(l_handle, cur_r.deptno || l_delim ||
 13                                  cur_r.dname  || l_delim ||
 14                                  cur_r.loc);
 15    end loop;
 16
 17    utl_file.fclose(l_handle);
 18  exception
 19    when others then
 20      utl_file.fclose(l_handle);
 21      raise;
 22  end;
 23  /

PL/SQL procedure successfully completed.

SQL> $type c:\temp\test.txt            --> because c:\temp is where EXT_DIR directory points to
10      ACCOUNTING      NEW YORK
20      RESEARCH        DALLAS
30      SALES   CHICAGO
40      OPERATIONS      BOSTON

SQL>
于 2021-04-19T18:18:09.123 回答