从 PL/SQL 游标中获取所有结果的任何简单方法?

Posted

技术标签:

【中文标题】从 PL/SQL 游标中获取所有结果的任何简单方法?【英文标题】:Any SIMPLE way to fetch ALL results from a PL/SQL cursor? 【发布时间】:2014-11-20 17:58:52 【问题描述】:

问题的第二部分:如何使用 SQL*Plus 做同样的事情(获得所有结果,没有任何循环)。

我正在编写一些 PL/SQL 脚本来使用 Jenkins 测试数据完整性。

我有一个这样的脚本:

declare
temp_data       SOME_PACKAGE.someRefCurFunction; // type: CURSOR
DATA1              NUMBER;
DATA2              NUMBER;
DATA3              SOMETHING.SOMETHING_ELSE%TYPE;

begin
  cursor := SOME_PACKAGE.someFunction('some',parameters,here);
  LOOP
   FETCH cursor INTO DATA1,DATA2,DATA3;
   EXIT WHEN temp_data%NOTFOUND;
   dbms_output.put_line(DATA1||','||DATA2||','||DATA3);
  END LOOP;
end;

结果如下所示:

Something1,,Something2
Something3,Something4,Something5
Something6,Something7,Something8

有时结果为空,如第一行所示。没关系,他们应该是。

这个脚本的目的很简单 - 从光标中获取所有内容,用逗号分隔数据,并打印带有结果的行。

这里的示例非常简单,但它只是示例。 “现实生活”包有时包含数百个变量,处理庞大的数据库表。

我需要它尽可能简单。

是否有任何方法可以从游标中获取所有内容,如果可能,用逗号分隔单个结果,然后将其发送到输出? Jenkins 测试的最终输出应该是一个文本文件,以便能够与其他结果进行比较。

提前致谢:)

【问题讨论】:

已经很简单了。 您能否详细说明您当前的实现有什么问题? (除了不是quoting values——但考虑到你的数据,这可能不是必需的,或者是吗?) @DaaaahWhoosh - 是的。但是我们需要一种更快的方法来生成配置文件和简单的 SQL*Plus 查询。我们必须用几乎无限的参数集测试几十个 PL/SQL 包。编写每个查询,这将比我提供的示例复杂几倍,或者更复杂 - 太昂贵了;) @SylvainLeroux - 实现没有错,它是正确的 FWIK。我需要的结果是:一个 SQL*Plus 查询执行与上面的代码相同的操作,而无需声明大量变量。我需要的是一个包含结果的文本文件,所以我可以将它与其他结果与其他参数集等进行比较。 【参考方案1】:

如果您真的愿意使用 SQL*Plus 脚本,而不是 PL/SQL 块

SQL> set colsep ','
SQL> variable rc refcursor;
SQL> exec :rc := SOME_PACKAGE.someFunction('some',parameters,here);
SQL> print rc;

应该执行该过程并从您的游标中获取所有数据。您可以使用spool 命令将生成的 CSV 输出假脱机到文件中。当然,您可能会遇到 SQL*Plus 无法以干净的格式显示数据的问题,因为 linesize 或其他类似问题 - 这可能会迫使您添加一些额外的 SQL*Plus 格式化命令(即set linesizecolumn <<column name>> format <<format>>等)

对我来说,SQL*Plus 脚本比编写一些动态 SQL 来为您带来更多收益并不明显,这些动态 SQL 会生成您最初发布的 PL/SQL 脚本,或者(如果您在 12c 上)编写一些使用 dbms_sql 的代码从返回的游标中获取数据。

【讨论】:

谢谢!我一定会检查一下,因为它可能就是我要找的!杰出的!我会让你知道它是否有效! 作为一个魅力,但格式化结果的问题是压倒性的;)【参考方案2】:

答案似乎很明显。您当前有一个函数,它返回一个游标本身,它返回一个包含数百个(但您只显示三个)字段的数据集。您需要一个带有逗号分隔值的字符串。因此,根据相同的查询更改函数或编写另一个函数。

package body SOME_PACKAGE
...
-- The current function
function someFunction ...
  returns ref_cursor ...
  -- create cursor based on:
  select f1, f2, f3 --> Three (or n) fields
  from ...
  where ...;
  return generated_cursor;
end function;

-- The new function
function someOtherFunction ...
  returns ref_cursor ...
  -- create cursor based on:
  select f1 || ',' || f2 || ',' || f3 as StringField --> one string field
  from ...
  where ...;
  return generated_cursor;
end function;
end package;

这并不是您所要求的全部。它确实保存了声明变量(一个而不是数百个)来一次读取一行中的数据,但是您仍然一次读取一行,而不是像我阅读您的问题那样,在一个操作中读取每一行。但如果这样的超级获取是可能的,它将需要大量的内存。有时我们做一些只需要大量内存的事情,我们只是尽力而为。但是您的“要求”似乎只是为了方便开发人员。这一点,imnsho,在消耗资源的优先级列表中很靠后。

在我看来,开发一个以您想要的最终形式返回数据的游标是最好的选择。

【讨论】:

以上是关于从 PL/SQL 游标中获取所有结果的任何简单方法?的主要内容,如果未能解决你的问题,请参考以下文章

PL/SQL:从两个函数之间传递的游标中获取

PL/SQL 编程游标存储过程函数

使用 PL/SQL 游标为报告工具返回结果集

从存储过程中调用 PL/SQL 游标得到结果

从光标获取值

如何在 Oracle PL/SQL 过程的开始部分之后声明游标