将所有查询结果转储到 plsql 块内的文件中
Posted
技术标签:
【中文标题】将所有查询结果转储到 plsql 块内的文件中【英文标题】:Dump all query results in file inside a plsql block 【发布时间】:2014-03-20 17:02:41 【问题描述】:我面临以下问题。我想执行一个查询并将所有结果导出到一个文件中。我的查询保存为 varchar2 类型,我可以立即执行它并给我所有结果。现在这些结果我如何将它们全部转储到一个文件中。我不想从查询或任何内容中选择特定的列名。这就像大量收集许多结果并将它们转储到文件中。这是我正在处理的一些伪代码:
这是一种行不通的方法
Declare
filehandle1 UTL_FILE.FILE_TYPE;
myquery varchar2(4000) := 'Select column1'||'~'||'Column2'||'~'||' from mytable';
Begin
filehandle1 := UTL_FILE.FOPEN ('MYDIR','mydata','W');
FOR emp IN (execute immediate (myquery)) LOOP --This part of course is not working
UTL_FILE.PUT (filehandle1, emp.*); --i dont want to write each column
END LOOP; --i have the columns and formatting ready of the query
UTL_FILE.FCLOSE (filehandle1);
End;
这又是另一种行不通的方法
Declare
filehandle1 UTL_FILE.FILE_TYPE;
myquery varchar2(4000) := 'Select column1'||'~'||'Column2'||'~'||' from mytable';
Begin
filehandle1 := UTL_FILE.FOPEN ('MYDIR','mydata','W');
UTL_FILE.PUT (filehandle1, myquery); --i want just to execute the query and write
UTL_FILE.FCLOSE (filehandle1); --everything in the file
End;
我怎样才能获取所有内容并将它们放入文件中?另外我这必须在 plsql 块中完成,因此我不能假脱机提前谢谢
【问题讨论】:
您的查询是否将所有列连接成一个字符串?目前,您显示的连接只是使查询无效,但我想那是伪代码;很难确定你真正的查询(和结果)会是什么样子。 是的,它将所有结果连接成一个字符串。我希望我的结果像 dfg~jjjjjj~67237~jlhn 我需要这些结果的原因是我想在一个文件中附加所有值并在其间添加一个分隔符,然后我将使用这个文件通过 sqlloader 加载它 【参考方案1】:您可以在光标上循环:
declare
filehandle1 utl_file.file_type;
myquery varchar2(4000) := 'select column1 ||''~''|| column2 from mytable';
mycursor sys_refcursor;
myresult varchar2(4000);
begin
filehandle1 := utl_file.fopen ('D42', 'mydata', 'w');
open mycursor for myquery;
loop
fetch mycursor into myresult;
exit when mycursor%notfound;
utl_file.put_line(filehandle1, myresult);
end loop;
close mycursor;
utl_file.fclose(filehandle1);
end;
/
或者更简单地说,如果你不需要查询是一个字符串(例如,我不确定你是否真的从另一个表中获取它,否则我不确定你为什么会有它作为varchar2
变量):
declare
filehandle1 utl_file.file_type;
begin
filehandle1 := utl_file.fopen ('D42', 'mydata', 'w');
for myrec in (select column1 ||'~'|| column2 as result from mytable)
loop
utl_file.put_line(filehandle1, myrec.result);
end loop;
utl_file.fclose(filehandle1);
end;
/
如果我创建表并将其填充为:
create table mytable (column1 number, column2 varchar2(10));
insert into mytable (column1, column2) values (1, 'First');
insert into mytable (column1, column2) values (2, 'Second');
然后使用其中任何一个,mydata
文件包含:
1~First
2~Second
如果您想明确使用批量收集,您可以这样做:
declare
filehandle1 utl_file.file_type;
myquery varchar2(4000) := 'select column1 ||''~''|| column2 from mytable';
mycursor sys_refcursor;
myresults sys.odcivarchar2list;
begin
filehandle1 := utl_file.fopen ('D42', 'mydata', 'w');
open mycursor for myquery;
loop
fetch mycursor bulk collect into myresults limit 100;
for idx in myresults.first..myresults.last loop
utl_file.put_line(filehandle1, myresults(idx));
end loop;
exit when mycursor%notfound;
end loop;
close mycursor;
utl_file.fclose(filehandle1);
end;
/
【讨论】:
我现在想到的但我不知道是否可以做的事情:我可以声明一个 clob 变量然后立即执行查询 BULK COLLECT INTO the clob 然后 utl_file.put_line(filehandle , clob 变量) 是否有可能做到这一点? 我也可以问你一些事情亚历克斯。让 sqlloader 处理这个文件。如果在 evryline 的末尾有一个新行,或者应该将数据全部附加到文件中没有新行的巨大堆中,这会有什么问题吗? 您不能将多个结果批量收集到一个clob
中,不。在某些时候,您必须遍历查询返回的行 - 无论是像我所做的那样将它们直接写入文件,还是将它们放入 clob(然后写出来......但为什么这样更好? );或批量收集到一个集合中并对其进行迭代以将它们写出来,但又不确定这会给您带来多少好处?
@GeorgeGeorgiou - 是的,或者改成for idx in 1..myresults.count loop
。失败的导出是否有 clob
字段,或者连接的字符串 > 4k?如果是这样,您需要重新考虑;如果不是clob
,那么您可以选择两个变量(每个clob 会更加复杂。否则...不确定,您可能需要针对失败的具体情况提出一个新问题。
@GeorgeGeorgiou - 是的,您需要将clob
分块写入(此站点上有示例),因此您必须自行选择该列,而不是作为其中的一部分串联。所以是的,特殊处理。不过,您可能也必须在 SQL*Loader 中对其进行特殊处理 - 请参阅 here for example。以上是关于将所有查询结果转储到 plsql 块内的文件中的主要内容,如果未能解决你的问题,请参考以下文章