2010-03-31 112 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