【问题标题】:return resultset from function in procedure从过程中的函数返回结果集
【发布时间】: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.queryPIPELINED 函数吗?如果是,您将无法在 PL/SQL 上下文中像这样检索它。它必须返回常规表类型。
  • @AndrewMcCoist - 是的,method4.query 是一个流水线函数。然而,虽然流水线对可扩展性很好,但解决方案并不需要它。我会相应地更新问题。

标签: oracle plsql


【解决方案1】:

我不相信这可以做到,因为似乎将一组不固定的列作为 PL/SQL 代码的一部分(作为 CTE 输入或其他类似方法)不允许将代码预先-编译。似乎唯一的答案是让整个过程保持动态。

回答我自己的问题我感觉很糟糕,但是当我得出这个结论时,我不想让它保持开放状态,并且删除这个问题可能会很糟糕,因为其他人将来可能会尝试这样做.. .

【讨论】:

    猜你喜欢
    • 2012-12-18
    • 1970-01-01
    • 1970-01-01
    • 2019-03-29
    • 2016-07-03
    • 1970-01-01
    • 2016-03-27
    • 2011-03-20
    • 1970-01-01
    相关资源
    最近更新 更多