从 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 linesize
、column <<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 游标中获取所有结果的任何简单方法?的主要内容,如果未能解决你的问题,请参考以下文章