Plsql Oracle 11g-如何声明记录以基于动态SQL存储值

Plsql Oracle 11g-如何声明记录以基于动态SQL存储值,plsql,oracle11g,dynamic-sql,Plsql,Oracle11g,Dynamic Sql,摘要 正如我的问题所说,我很想知道如何定义记录,以便存储通过动态SQL检索的值。我有一个在CLOB列中存储SQL的表。最终目标是使用要运行的查询的查询id调用管道函数。我目前的问题是不知道如何定义类型,这样我就可以通过管道输出数据。我无法定义管道函数,因为在声明管道函数时,它需要一个类型。在本例中,类型将根据查询表中包含的所需查询进行更改 我尝试过的 我已经阅读了DBMS_SQL的使用,我发现DBMS_SQL的一个特性是DBMS_SQL.DEFINE_COLUMN,但是它要求我明确定义列,除非我

摘要

正如我的问题所说,我很想知道如何定义记录,以便存储通过动态SQL检索的值。我有一个在CLOB列中存储SQL的表。最终目标是使用要运行的查询的查询id调用管道函数。我目前的问题是不知道如何定义类型,这样我就可以通过管道输出数据。我无法定义管道函数,因为在声明管道函数时,它需要一个类型。在本例中,类型将根据查询表中包含的所需查询进行更改

我尝试过的

我已经阅读了DBMS_SQL的使用,我发现DBMS_SQL的一个特性是
DBMS_SQL.DEFINE_COLUMN
,但是它要求我明确定义列,除非我在这里遗漏了什么。再一次。。。我不知道从动态sql返回的列类型。。。它们可以是任何东西,以任何顺序排列

我的问题示例

下面的代码是我的问题的最简单示例。我希望在下面的示例代码中填充的记录是
rec\u cursor\u query
。在所有其他非动态sql中,它将基于表定义,或使用列名和%TYPE关键字显式定义<代码>无法使用此:记录\u光标\u查询员工%ROWTYPE

DECLARE

  /* Cursor Pointer */
  cur_Query   SYS_REFCURSOR;

  /* Store Dynamic SQL */
  q           VARCHAR2(2000);

  /* Declare Record based on Dynamic SQL */
  --rec_cursor_query  ????table%ROWTYPE;  /* I realize I can't do this... but what can I do? */

BEGIN

  /* Fake Query Below saved into q */
  q   :=    q'~SELECT 1001 AS pkey, 'Jake' AS firstname, 'Johnson' AS lastname FROM dual~';

  /* Output Query just to show query was saved */
  dbms_output.put_line(q);

  OPEN cur_Query FOR
    q;

  LOOP

    FETCH cur_Query INTO rec_cursor_query; /* Again here... I can't do this due to it not being Defined */

    EXIT WHEN cur_Query%NOTFOUND;

  END LOOP;

  CLOSE cur_Query;


END
;

很简单,这在Oracle SQL中是不可能的。SQL是强数据类型的。对我们来说,这些“如果看起来像鸭子”的废话都不是废话!
table()
函数只适用于预定义类型(通常是SQL对象),因为它需要知道投影。如果您想知道,我们不能使用ANYDATASET或ANYTYPE作为流水线函数的返回值(PLS-00630:流水线函数必须具有受支持的集合返回类型)

可以尝试的一个选项是通过为流水线函数动态生成SQL类型和为调用动态生成的SQL的流水线函数动态生成PL/SQL来接收代码。但是,您现在正处于作为查询的一部分执行DDL的领域,这真的很麻烦。简言之,我认为这可能有效——尽管我从未尝试过——但我想说,这种方法在生产中使用起来太不稳定了


另一个选择是认识到SQL对于这项工作来说是错误的工具。还有其他一些语言本机支持反射和元数据驱动的功能。使用弱引用游标将数据传递给客户端应用程序。Ref游标映射到ODBC和JDBC结果集,这些结果集可以动态解释投影。或者升级到Oracle 12c,它引入了对DBMS_SQL中隐式结果集的支持

@hotfix-No。。。可以为CLOB列中表中存储的任何查询打开游标。当然,我在代码中遗漏了一些混乱的细节,因为这些细节在解决我的问题时是不必要的。管道函数将接受查询id作为参数,然后通过管道将表返回给用户。我缺少一个重要的组成部分。。。声明类型。我不知道您的表中存储了多少select,但您可以为每个select单独的过程编写。对于所有情况,一个程序都是一个坏主意。@hot恰好修复了。。。我仍然不确定这是否可能。或者我应该说。。。我知道这是可能的,因为我使用的应用程序提供了这样一个功能。现在,当我为自己开发这个时,我现在无法理解它。这是最令人沮丧的部分。。。知道这是可能的,但不知道如何实现。SQL总是需要知道投影,因此我认为它永远不会让您的查询显示
'select*from[I not know what]
。感谢您提供了可靠的答案。根据您在回答中所说的,动态创建PL/SQL而不仅仅是普通SQL是可能的吗?我还没有探索过这一点,但我想知道这是否可能。同样,从你的回答来看,这意味着这是可能的。如果是这样的话,我觉得它仍然值得探索,即使只是为了教育目的。谁知道。。。这对我来说可能是一个潜在的解决方案,动态地构建SQL类型和PL/SQL函数绝对是可能的。问题是什么叫它们?您可以动态生成代码来调用动态生成的代码。但在某个时刻,递归必须停止,您需要具体的静态代码。这始终是难点。特别是在多用户环境中部署此类代码时。只要它是一个人的玩具,你就可以逃脱惩罚。