2015-03-02 70 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