【发布时间】:2016-10-15 06:03:11
【问题描述】:
很像this question,我希望从函数中返回一个结果集,并像处理普通表一样使用这个结果集,但是我想在一个过程中执行此操作(使用 Oracle 版本 > = 11)。
我的基本意图是允许将动态查询的结果用作非常复杂的静态 SQL 语句的起点。
对于直接来自 SQL*PLUS 提示符的调用,存在多种解决方案,但在过程中运行时它们似乎都失败了。例如,使用'method4':
SQL> WITH q AS (SELECT * FROM TABLE(method4.query('select id, pid from
2 my_table where rownum < 100')))
3 SELECT * FROM q where rownum <4;
ID PID
--------------- ----------
72 499
11 89
13 23
3 rows selected.
SQL> CREATE OR REPLACE PROCEDURE test_x (
2 p_sql IN VARCHAR2,
3 p_results OUT SYS_REFCURSOR
4 ) IS
5 BEGIN
6 open p_results for
7 WITH q AS (SELECT * FROM TABLE(method4.query(p_sql)))
8 SELECT * FROM q where rownum <4; -- this is where the complex logic would go
9 END test_x;
10 /
Warning: Procedure created with compilation errors.
SQL> show errors
Errors for PROCEDURE TEST_X:
LINE/COL ERROR
-------- -----------------------------------------------------------------
7/4 PL/SQL: SQL Statement ignored
7/29 PL/SQL: ORA-22905: cannot access rows from a non-nested table
item
SQL>
在我的实际应用程序中,过程中的查询会很长很复杂。我想避免为每个调用生成动态 SQL。 (这是我目前的“后备”解决方案。)
有没有办法在存储过程中利用“ANYDATASET 表函数”?
更新: 我被告知在 PL/SQL 上下文中接收流水线内容是不可能的。我相信这只会给我留下一个非流水线的方法 - 我相信它有同样的问题......
给定以下初始 SQL 的非流水线模拟:
SQL> CREATE OR REPLACE FUNCTION myQuery (
2 p_1 IN VARCHAR2
3 ) RETURN ANYDATASET AS p_result ANYDATASET;
4 BEGIN
5 EXECUTE IMMEDIATE p_1 INTO p_result;
6 RETURN(p_result);
7 END myQuery;
8 /
Function created.
SQL> CREATE OR REPLACE PROCEDURE test_x2 (
2 p_sql IN VARCHAR2,
3 p_results OUT SYS_REFCURSOR
4 ) IS
5 myset anydataset;
6 BEGIN
7 myset := method4.query(p_sql);
8 open p_results for
9 WITH q AS (SELECT * FROM TABLE(myset))
10 SELECT * FROM q where rownum <4; -- this is where the complex logic would go
11 END test_x2;
12 /
Warning: Procedure created with compilation errors.
SQL> show errors
Errors for PROCEDURE TEST_X2:
LINE/COL ERROR
-------- -----------------------------------------------------------------
9/7 PL/SQL: SQL Statement ignored
9/32 PL/SQL: ORA-22905: cannot access rows from a non-nested table
item
106/13 PLS-00653: aggregate/table functions are not allowed in PL/SQL
scope
在 PL/SQL 中似乎不允许使用表函数 - 与流水线无关。
如果是这样,是否有任何其他方法可以获取生成的架构可以是任何内容的动态查询,并将其作为“with”输入提供给后续静态查询,所有这些都在 PL/SQL 过程中?
【问题讨论】:
-
我相信您应该首先将函数中的值分配给某个变量。在您的过程中,声明函数返回类型的变量并将函数结果分配给该变量。然后,在
SELECT * FROM TABLE语句中使用您的变量。 -
@AndrewMcCoist - 感谢您的建议,但它似乎只是将错误移动到我设置变量的行。 (“myset := method4.query(p_sql);”这一行会发现 ORA-22905 错误。)
-
哦。我忘了。你的
method4.query是PIPELINED函数吗?如果是,您将无法在 PL/SQL 上下文中像这样检索它。它必须返回常规表类型。 -
@AndrewMcCoist - 是的,
method4.query是一个流水线函数。然而,虽然流水线对可扩展性很好,但解决方案并不需要它。我会相应地更新问题。