Oracle 编写一个函数/过程,将大约150k行合并为一行,并将其作为输出发送,以便能够从UI下载

Oracle 编写一个函数/过程,将大约150k行合并为一行,并将其作为输出发送,以便能够从UI下载,oracle,plsql,cursor,pipelined-function,Oracle,Plsql,Cursor,Pipelined Function,我想获得一些关于实现下面提到的场景的最佳方法的信息。我只是在这里寻找一种替代的最佳方法,而不是调试错误 我有一个select语句,它生成大约150K行,大约10列。我需要用制表符分隔符连接列,然后循环遍历每一行,并将所有列组合成一行。正在使用函数调用此列值,并从UI下载 TYPE OUT_REC_CSV_TYP IS RECORD ( object_status VARCHAR2 ( 4000 ) , extract_

我想获得一些关于实现下面提到的场景的最佳方法的信息。我只是在这里寻找一种替代的最佳方法,而不是调试错误

我有一个select语句,它生成大约150K行,大约10列。我需要用制表符分隔符连接列,然后循环遍历每一行,并将所有列组合成一行。正在使用函数调用此列值,并从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'));
目前的做法: 编写一个流水线函数,将其作为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'));

我可能用错了词。 预期输出:所有行合并为一行,以新行分隔 A列B列C列D列 155189测试ABCD 127557测试ABCD ....... 大约15万行

这种方法有时会抛出一个错误,并在多次尝试下载此clob值文本文件后生效。

(150K行)*(10列)在一行中?你是这么说的吗?谁能理解其中所写的内容(mind选项卡作为列分隔符,以及可能的空值)

另一方面,您发布的代码看起来好像每一行都有自己的行;这:

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\u文件
。不过,这种方法需要访问目录(通常位于数据库服务器上)


我不确定这里的问题是什么。如果您需要调试错误的帮助,我们需要更多信息,例如错误。还有一个可复制的测试用例,我们可以在本地运行。如果您正在寻找最佳实践,我会后退一大步,解释实际需求是什么,因为这看起来是一种非常奇怪的方法。中间层是否将不同的行连接在一起,生成一个文件,然后发送到客户机?当我们试图从UI下载时,会发生错误。我们不确定它是与文件大小有关,还是与流量有关,因为它有时没有任何问题,有时我们尝试了2/3次。下面的循环将新行作为新行添加到第一行,依此类推。在循环结束时,我们使用新的行分隔符将所有行合并为一行,然后通过管道将整个clob循环V_OUT_REC.extract_csv:=V_OUT_REC.extract_csv | CHR(10)| i.extract_csv;端环;管道排(V_OUT_REC);你明白,对,调试来自未知组件的未知错误是不可靠的,并且可能是系统加载的结果,这里的任何人都无法做到,对吧?你会得到什么错误?甲骨文错误?客户端出现网络错误?除此之外,您可以创建一个返回CLOB的函数,而不使用流水线函数<代码>选择程序包名称。从DUAL获取CSV提取('04/19/2021','1')应该会得到相同的结果,但开销较小。也许错误会消失。:-)我可能用错了词。预期输出:所有行合并成一行,由新行COLU a COLU B COLU C COLU D COLU E 155189 TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST ABCD分隔。为了避免混淆,您可能希望在发布的原始消息中修复此问题。我在开头添加了一个标题。因此,每一列都由一个制表符分隔,我们如何从Linux服务器上的oracle数据库检索文件并将文件发送给调用者。创建了一个目录,并使用上面提到的UTL_文件保存该文件。谢谢。我找到了解决办法。