2012-09-25 30 views
2

我想在我的流水线函数中执行动态查询并返回此查询的结果。 可以做到这一点吗? 流水线函数对我来说很方便,因为它可以像表格一样为我的应用程序实现良好的接口。PL/SQL - 立即执行流水线函数

功能:

CREATE OR REPLACE FUNCTION MyFunction(p_schema VARCHAR2) RETURN MyTableType Pipelined IS 
v_query VARCHAR2(1000); 
BEGIN 
    v_query := 'SELECT * FROM TABLE ('||p_schema||'.somepackage.SomeFunction)'; --SomeFunction is another pipelined function 
    EXECUTE IMMEDIATE v_query; 
    --Results of the v_query are compatible with MyTableType's row type. But how to return them from pipelined function? 
END; 

回答

1

我觉得是这样的:只有

CREATE OR REPLACE FUNCTION MyFunction(par1 VARCHAR2, ...) RETURN MyTableType Pipelined IS 
v_query VARCHAR2(1000); 
l_result MyTableType; 
BEGIN 
    v_query := --My query created based on parameters 
    EXECUTE IMMEDIATE v_query into l_result; 

    pipe row(l_result); 
END; 

工作,如果v_query返回1行。

3

可以组合动态SQL和流水线函数,但返回类型不会是动态的:返回的列的数量和类型将被修复。

您可以使用EXECUTE IMMEDIATEBULK COLLECT(感谢@be here now),dynamic cursorsDBMS_SQL返回多行。下面是一个例子与动态光标:

SQL> CREATE OR REPLACE PACKAGE pkg AS 
    2  TYPE test_tab IS TABLE OF test%ROWTYPE; 
    3  FUNCTION dynamic_cursor(l_where VARCHAR2) RETURN test_tab PIPELINED; 
    4 END; 
    5/

Package created. 

SQL> CREATE OR REPLACE PACKAGE BODY pkg IS 
    2  FUNCTION dynamic_cursor(l_where VARCHAR2) RETURN test_tab PIPELINED IS 
    3  cc sys_refcursor; 
    4  l_row test%ROWTYPE; 
    5  BEGIN 
    6  OPEN cc FOR 'SELECT * FROM test WHERE ' || l_where; 
    7  LOOP 
    8   FETCH cc INTO l_row; 
    9   EXIT WHEN cc%NOTFOUND; 
10   PIPE ROW (l_row); 
11  END LOOP; 
12  RETURN; 
13  END; 
14 END; 
15/

Package body created. 

我们称之为动态功能:

SQL> SELECT * 
    2 FROM TABLE(pkg.dynamic_cursor('id <= 2')); 

     ID DAT 
---------- --- 
     1 xxx 
     2 xxx 

像往常一样使用动态SQL,谨防SQL Injection

+0

@dzb:'DBMS_SQL'不会让查询快速通过魔法:),实际上比原生动态SQL有更多的开销。有很多原因可能会导致您的查询速度变慢,因此我无法通过如此少的上下文来了解如何提高其性能。动态和静态SQL之间的唯一区别是使用变量。您是否使用[参数化动态SQL](http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/dynamic.htm#BHCGEFCA)? –

+0

感谢这个例子。它工作但可怕的缓慢。我认为这是因为我在我的查询中调用另一个流水线函数(我更新了我的问题),看起来它被调用了太多次。你可以发布一些建议给dbms_sql吗? – dzb

+1

@VincentMalgrat'立即执行...批量收集到...;为我在col.first .. col.last循环管道行()结束循环;'? –