2015-03-02 32 views
3

例如管道函數,如果我有這種功能
與光標參數預言

function test_pipe(p_source in t_cursor) 
return t_tab 
pipelined 
as --some code goes here 

t_cursor是一個引用遊標。 我知道如果我在一個包聲明光標並希望將它作爲參數傳遞我可以調用這個函數像

select * from table(test_pipe(cursor(select 1 from dual))); 

但什麼。 這樣的事情。

procedure test is 
v_ct pls_integer; 
cursor main_cur is select 1 from dual; 
begin 
select count(*) into v_ct from table(test_pipe(main_cur)); 
--some code 
end; 

,我得到main_cur無效identifier-- PL/SQL:ORA00904錯誤。 我該如何編寫代碼才能將main_cur作爲參數傳遞給test_pipe?

+0

您將n eed將'rowsource'傳遞給流水線功能。遊標只是指向結果集的指針。看到我的答案。 – 2015-03-02 12:16:12

回答

4

cursor main_cur is select 1 from dual;

遊標是用於從結果集中提取行的指針。

所以,當你做table(test_pipe(main_cur)),你是不是傳遞一個行來源管道函數。您需要首先獲取行並傳遞行源。

測試用例:

SQL> CREATE or replace TYPE target_table_row 
    2 AS 
    3 OBJECT 
    4 (EMPNO NUMBER(4) , 
    5  ENAME VARCHAR2(10) 
    6  ) 
    7/

Type created. 

SQL> 
SQL> sho err 
No errors. 
SQL> 
SQL> CREATE or replace TYPE target_table_rows 
    2 AS 
    3 TABLE OF target_table_row; 
    4/

Type created. 

SQL> 
SQL> sho err 
No errors. 
SQL> 

管道功能

SQL> CREATE OR REPLACE FUNCTION pipelined_fx(
    2  p_cursor IN SYS_REFCURSOR) 
    3 RETURN target_table_rows PIPELINED PARALLEL_ENABLE(
    4  PARTITION p_cursor BY ANY) 
    5 IS 
    6 TYPE cursor_ntt 
    7 IS 
    8 TABLE OF emp%ROWTYPE; 
    9 nt_src_data cursor_ntt; 
10 BEGIN 
11 LOOP 
12  FETCH p_cursor BULK COLLECT INTO nt_src_data LIMIT 100; 
13  FOR i IN 1 .. nt_src_data.COUNT 
14  LOOP 
15  PIPE ROW (target_table_row(nt_src_data(i).empno, nt_src_data(i).ename)); 
16  END LOOP; 
17  EXIT 
18 WHEN p_cursor%NOTFOUND; 
19 END LOOP; 
20 CLOSE p_cursor; 
21 RETURN; 
22 END pipelined_fx; 
23/

Function created. 

SQL> 
SQL> show errors 
No errors. 
SQL> 

現在,讓我們來測試管道函數

SQL> DECLARE 
    2 rc SYS_REFCURSOR; 
    3 num NUMBER; 
    4 BEGIN 
    5 OPEN RC FOR SELECT * FROM emp; 
    6 SELECT count(*) INTO num FROM TABLE(pipelined_fx(rc)); 
    7 DBMS_OUTPUT.PUT_LINE(num || ' rows in total.'); 
    8 END; 
    9/
14 rows in total. 

PL/SQL procedure successfully completed. 

SQL> 
+0

謝謝你的支持回覆 – arminrock 2015-03-02 12:26:59

+0

不客氣。 – 2015-03-02 12:28:57

3

A cursor expression相當於一個參考光標。 An explicit cursor是一個不同的,不可互換的;您可以使用dbms_sql包在ref遊標和遊標變量之間進行一些交換,但不能使用像這樣的顯式遊標。

我可以看到你彷彿想要最接近的是有打開與the `open for syntax相同的查詢遊標變量:

procedure test is 
    v_ct pls_integer; 
    main_cur t_cursor; 
begin 
    open main_cur for select 1 from dual; 
    select count(*) into v_ct from table(test_pipe(main_cur)); 
    close main_cur; 
    dbms_output.put_line('Count is: ' || v_ct); 
    --some code 
end test; 

但是,這是不太一樣的東西,所以可能不適當。我不知道你爲什麼想用循環以外的顯式遊標來做任何事情。


誤入XY領土這裏,因爲這是無關,與你原來問過,但來自評論你似乎希望能夠聚集在遊標中的數據;你可以用分析計數來代替。作爲一個非常簡單的例子,如果你的光標查詢是這樣做的:

select trace, col1 
from t42 
order by trace, col1; 

,那麼你可以添加計算每個痕跡值的另一列:

select trace, col1, 
    count(col1) over (partition by trace) as trace_count 
from t42 
order by trace, col1; 

然後,您可以參考列在遊標循環。或者,如果你在其中計數是一個行想只循環,你的光標可以使用,作爲一個子查詢:

select trace, col1 
from (
    select trace, col1, 
    count(col1) over (partition by trace) as trace_count 
    from t42 
) 
where trace_count = 1 
order by trace, col1; 

SQL Fiddle demo

+0

感謝您的回覆 – arminrock 2015-03-02 12:39:19

+0

@arminrock - 沒問題。我沒有打算顯示流水線函數,因爲你說你已經有這部分工作,但我測試了這個程序在同一個包中,這似乎是你在做什麼。與Lalit一樣,除了他在一個匿名塊中。 – 2015-03-02 12:43:32

+0

是「開放的」工作,但說實話我的主要問題是從顯式光標計數並對其進行分組。我使用流水線函數編寫它,它在實際生活中看起來有點不同 select count(*),通過count(*)= 1的跟蹤跟蹤到表(test_pipe(main_cur))組中的v_ct,v_trace; 也許你可以建議一個更好的方法來從顯式遊標獲取聚合,我只是不想重複選擇一遍又一遍,因爲它太長,這就是爲什麼我使用顯式遊標。 – arminrock 2015-03-02 12:59:41