2010-03-31 108 views
2

我正在处理pl sql存储过程。 我需要的是做一个选择,使用游标,并为每个记录使用值构建一个字符串。 最后我需要把它写入一个文件。 我尝试使用dbms_output.put_line(“toto”),但缓冲区大小很小,因为我有大约1400万行。 我从unix ksh调用我的过程。 我在想使用“spool on”(在ksh端)来转储我的过程结果,但我不知道如何去做(如果可能的话)Oracle PL/SQL:将查询结果转储到文件中

任何人都有任何想法?

+0

出于好奇,你试试我的解决方案? – 2010-03-31 12:30:35

+0

我已经回答了。我无法承受更多的一次查询。您的解决方案(分析函数)需要查询被执行多个。另一种解决方案不起作用,因为我需要从前面的迭代中获得一个字段的值。 – 2010-03-31 15:40:08

+0

为什么您需要使用分析函数多次执行查询?你读过我的最后一条评论吗? – 2010-03-31 15:53:06

回答

8

除非真的有必要,否则我不会使用程序。

如果调用使用SQL 加上剧本,只是把下面的内容test.sql(在SET s是SQLPlus FAQ去除噪声):

SET ECHO OFF 
SET NEWPAGE 0 
SET SPACE 0 
SET PAGESIZE 0 
SET FEEDBACK OFF 
SET HEADING OFF 
SET TRIMSPOOL ON 
SET TAB OFF 

Select owner || ';' || object_name 
From all_objects; 

QUIT 

和输出重定向到文件(test.txt):

sqlplus user/[email protected]ce @ test.sql > test.txt 

如果你真的需要做的东西在PL/SQL,考虑把该进的功能和Ca LL它每个记录:

Create Or Replace Function calculate_my_row(in_some_data In Varchar2) 
    Return Varchar2 
As 
Begin 
    Return in_some_data || 'something-complicated'; 
End calculate_my_row; 

电话:

Select owner || ';' || calculate_my_row(object_name) 
From all_objects; 

业绩可能遭受负面,但它应该工作。请确保,尽管如此,您尝试使用纯粹的SQL无法完成。


阅读您的评论我觉得解析函数Lag是你所需要的。

这个例子追加*的情况下val值发生了变化:

With x As (
     Select 1 id, 'A' val FROM dual 
Union Select 2 id, 'A' val FROM dual 
Union Select 3 id, 'B' val FROM dual 
Union Select 4 id, 'B' val FROM dual 
) 
--# End of test-data 
Select 
    id, 
    val, 
    Case When (val <> prev_val Or prev_val Is Null) Then '*' End As changed 
From (
    Select id, val, Lag(val) Over (Order By id) As prev_val 
    From x 
) 
Order By id 

返回

 ID V C 
---------- - - 
     1 A * 
     2 A 
     3 B * 
     4 B 
+0

这也不起作用,因为问题是我需要为每一行做一些东西,所以我做了一个游标,并在里面为每一行做我的东西。 – 2010-03-31 08:18:39

+0

请看我更新的答案。你在尝试什么,不能在纯SQL中完成? – 2010-03-31 08:31:58

+0

不坏这个解决办法,但... :) 我在每一行做的treatement是: 如果字段的前值是不同的,目前的价值,我会串连东西,别的什么也不做。 因此,使用它的游标工作,但我不能/我不知道如何转储结果。 – 2010-03-31 08:42:37

0

utl_file是你的朋友 http://www.adp-gmbh.ch/ora/plsql/utl_file.html 但是写入数据到服务器上的文件系统,所以你可能需要你的DBA的帮助。

+0

我看到了utl_file,但我无法使用它,因为我没有权限。 – 2010-03-31 08:09:06

1

如果输出的每一行都是表格中一行操作的结果,那么存储函数与Peter Lang的答案一起可以完成您所需的操作。

create function create_string(p_foobar foobar%rowtype) return varchar2 as 
begin 
    do_some_stuff(p_foobar); 
    return p_foobar.foo || ';' ||p_foobar.bar; 
end; 
/

如果它要复杂得多,也许你可以使用一个流水线表函数

create type varchar_array 
    as table of varchar2(2000) 
/

create function output_pipelined return varchar_array PIPELINED as 
    v_line varchar2(2000); 
begin 
    for r_foobar in (select * from foobar) 
    loop 
    v_line := create_string(r_foobar); 
    pipe row(v_line); 
    end loop; 
    return; 
end; 
/

select * from TABLE(output_pipelined); 
+0

我在尝试这个解决方案,但是由于我有大量的数据,我可以使用它吗? v_line将有更多的2000个字符?它仍然有效吗?或者在v_line中只是一行的信息? – 2010-03-31 09:24:38

+0

v_line是一行的信息。 – 2010-03-31 10:48:56

+0

太好了。有用。非常感谢。 – 2010-03-31 11:51:30