oracle - 编写一个函数/过程,将大约 150k 行合并为一个,并将其作为输出发送,以便能够从 UI 下载
问题描述
我想就执行以下提到的场景的最佳方法获得一些意见。我只是在这里寻找一种替代的最佳方法,而不是调试错误。
我有一个 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 值文本文件后起作用。
解决方案
(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>
推荐阅读
- dart - 根据方向改变脚手架内容的正确方法
- javascript - 使用 JavaScript 后不返回显示块的初始 css 设置
- python - 使用 needs_threshold 作为 make_scorer 函数的参数有什么用?
- java - Java - 使用给定的 consumerKey、consumerSecret、accessToken、accessTokenSecret 和 realm 执行 oAuth1.0 认证请求
- flex-lexer - 行结束 lex
- javascript - 构建一个按钮以每次生成一个新类
- json - 为什么我的 json 不能将列表中的所有对象解析为带有标题的不同行?
- javascript - 来自兄弟组件的子组件的 google-maps-react onClick onMarkerClick
- c - 双端队列,按引用调用(创建标头)
- c++ - 如何将此代码从 C 转换为 C++?