从 Oracle 中的动态 SQL 获取结果集中的结果

Mic*_*ens 5 oracle resultset dynamic-sql oracle-sqldeveloper

这个问题与我在 StackOverflow 上找到的其他几个问题类似,但这些差异对我来说足够重要,值得提出一个新问题,所以这里是:

我想从Oracle中的动态SQL获取一个结果集,然后将其作为结果集显示在类似SqlDeveloper的工具中,就像我直接执行动态SQL语句一样。这在 SQL Server 中很简单,所以具体来说,下面是 SQL Server 中的一个示例,它在 SQL Server Management Studio 或查询资源管理器中返回结果集:

EXEC sp_executesql N'select * from countries'
Run Code Online (Sandbox Code Playgroud)

或者更恰当地说:

DECLARE @stmt nvarchar(100)
SET @stmt = N'select * from countries'
EXEC sp_executesql @stmt
Run Code Online (Sandbox Code Playgroud)

问题“如何从执行动态 SQL 的 Oracle PL/SQL 匿名块返回结果集/游标?” 解决了问题的前半部分——在游标中执行动态 SQL。问题“如何使Oracle过程返回结果集”提供了类似的答案。网络搜索揭示了同一主题的许多变体,所有这些都只解决了我问题的前半部分。我发现这篇文章解释了如何在 SqlDeveloper 中执行此操作,但这使用了 SqlDeveloper 的一些功能。我实际上使用的是自定义查询工具,因此我需要将解决方案独立于 SQL 代码中。该自定义查询工具同样不具备显示 print (dbms_output.put_line) 语句输出的功能;它只显示结果集。这是使用“立即执行...批量收集”的另一种可能途径,但此示例再次使用 dbms_output.put_line 语句循环呈现结果。此链接试图解决该主题,但该问题也从未得到完全解答。

假设这是可能的,我将添加一个条件:我想在不必定义函数或过程的情况下执行此操作(由于数据库权限有限)。也就是说,我想执行一个包含动态 SQL 的独立 PL/SQL 块,并在 SqlDeveloper 或类似工具中返回结果集。


总结一下:

  • 我想执行任意 SQL 语句(因此是动态 SQL)。
  • 该平台是Oracle。
  • 解决方案必须是没有过程或函数的 PL/SQL 块。
  • 输出必须生成为规范结果集;没有打印语句。
  • 输出必须在 SqlDeveloper 中呈现为结果集,而不使用任何 SqlDeveloper 特殊功能。

有什么建议么?

Gar*_*ers 1

您似乎要求一大块 PL/SQL 代码,该代码将采用任意查询返回未确定结构的结果集,并以某种方式“转发/重组”该结果集,以便可以通过某些“自定义 GUI 工具轻松呈现” ”。

如果是这样,请查看 DBMS_SQL 中的动态 SQL。它有一个 DESCRIBE_COLUMNS 过程,该过程从动态 SELECT 语句返回列。您需要的步骤是,

  1. 解析语句
  2. 描述结果集(列名称和数据类型)
  3. 获取每一行,对于每一列,调用与数据类型相关的函数以将该值返回到局部变量中
  4. 将这些局部变量放入定义的结构中以返回到调用环境(例如一致的列名称[例如col_1,col_2]可能都是VARCHAR2)

作为替代方案,您可以尝试将查询构建到XMLFOREST语句中,并从 XML 中解析结果。


补充:与 SQL Server 不同,Oracle PL/SQL 调用不会“自然”返回单个结果集。它可以打开一个或多个引用游标并将它们传回客户端。然后,客户端有责任从这些引用游标中获取记录和列。如果您的客户端不/无法处理该问题,则您无法使用 PL/SQL 调用。存储函数可以返回预定义的集合类型,这可以让您执行诸如“select * from table(func_name('select * from states'))”之类的操作。但是,该函数无法执行 DML(更新/删除/插入/合并),因为它破坏了该查询的任何一致性概念。另外,返回的结构是固定的,因此

select * from table(func_name('select * from countries'))
Run Code Online (Sandbox Code Playgroud)

必须返回相同的列集(列名和数据类型)

select * from table(func_name('select * from persons'))
Run Code Online (Sandbox Code Playgroud)

使用 DBMS_SQL 或 XMLFOREST,这样的函数可以接受动态查询并将其重组为预定义的列集(col_1、col_2 等),以便可以以一致的方式返回它。但我不明白这有什么意义。