打开 PL/SQL 语句的引用器?

Posted

技术标签:

【中文标题】打开 PL/SQL 语句的引用器?【英文标题】:Open a refcursor for a PL/SQL statement? 【发布时间】:2015-04-07 15:33:04 【问题描述】:

我正在使用 Oracle 和 s-s-rS 为企业创建报告。该报告要求我汇总连续的序列号范围,这些序列号可以由字母数字组成。

例如,假设我有以下连续剧:

OPS114
OPS115
OPS116
OPS117
OPS145
OPS146
OPS160
890RPT
896RPT
897RPT

报告应该有每个连续范围的单个聚合行,以及每个范围的计数,如下所示:

OPS114 - OPS117 (4)
OPS145 - OPS146 (2)
OPS160 - OPS160 (1)
890RPT - 890RPT (1)
896RPT - 897RPT (2)

我已经提取了我需要的数据,并将其批量收集到一个表变量中。现在,我需要聚合行 - 如果我只需要操作数据,这还不错,但我需要将其作为对 refcursor 的查询。我可以为 PL/SQL FOR 循环打开一个 refcursor,还是我在叫错树?我试图用谷歌搜索这个,但“循环光标”不是我想要的。另一种方法是尝试使用 VB 在 s-s-rS 中聚合结果。 (所以无论哪种方式,这都不是一个好时机。)我不确定我是否有权为此创建一个 SQL 表类型,所以这是我寻求的替代方案。

如果有人对此有任何经验,将不胜感激!

【问题讨论】:

使用 pivot 或 stragg 或 listagg 聚合数据,然后打开 ref_cursor 以返回结果。您在哪里需要更多帮助? @kevinsky Pivot 无法满足我的需求。您的评论只是帮助我了解了 STRAGG 和 LISTAGG - 后者似乎更接近我可能需要的,但我不确定我是否可以获得我想要的结果(或我需要的显示)。是的,这些内置函数确实返回了一个结果集,但除非我可以将自定义排序函数传递给它们,否则我怀疑它们是否能满足我的需要。我需要更多帮助的地方 - 我想要一个自定义 PL/SQL 函数将结果写入引用。这可能吗? 当然,您可以使用自定义的用户创建函数或内置函数。为了回答您的问题,您能否提供表格结构和任何其他相关细节? 从函数返回SYS_REFCURSOR 的一个简单示例是this answer。 【参考方案1】:

您可以通过一条 SQL 语句来完成此操作,但您需要更好地定义数据。您的列存储字符串,但您将它们用作数字来查找范围。似乎数字部分可以在字符串部分之前或之后。

如果您能够编写一些逻辑来分离出这样的数字(并且可能将字符串部分保留在另一列中)-

114
115
116
117
145
146
160
890
896
897

然后它简化为一个简单的gaps and islands 问题。

第 1 步 - 选择 rownum 以及该列(这将是从 1 开始的连续序列)

第 2 步 - 从此数值数据列中减去 rownum。

第 3 步 - 按结果分组

第 4 步 - 从组中获取 min(numeric value) 和 max(numeric value) 和 count(numeric value),这将是组合为字符串时的结果。

Numeric_part     Rownum      Difference
------------     ------      ------------
114              1           113
115              2           113
116              3           113
117              4           113
145              5           140
146              6           140
160              7           153
890              8           882
896              9           887
897              10          887

按差异列分组,你得到 -

Difference     Min(num)    Max(num)    count(num)   Result
----------     ---------   ----------  ----------   -----------------
113            114         117         4            114 - 117 (4)
140            145         146         2            145 - 146 (2)
153            160         160         1            160 - 160 (1)
882            890         890         1            890 - 890 (1)
887            896         897         2            896 - 897 (2)

可以在 PLSQL 中使用该 SQL 语句返回一个游标,如 @MickMnemonic 在 cmets 中的 this 链接。

基本上——

OPEN cursor_variable FOR SELECT something FROM something...;

【讨论】:

虽然我找到了解决这个问题的方法,但取决于我们对数据进行排序的方式,我认为这是一个更好的答案。如果我们不必对字符数据进行排序,那么更改表定义绝对是合乎逻辑的,并且会使事情变得更容易和更快(我使用正则表达式调用来分隔每个循环迭代中的数据)。也就是说,我们似乎确实有“AB123C”、“B456CD”等记录......所以我们实际上可能需要对字符数据进行排序。如果是这种情况,确定范围可能会更加困难。【参考方案2】:

我与一位同事谈及此事,他有一个想法,我已经能够实施。

我能够创建一个流水线函数来处理我的数据选择和转换;这允许我根据需要聚合我的行,并且仅在连续范围完成后才传递行。

我现在使用SELECT ... FROM TABLE(MYFUNCTION()) 语法从过程中调用该函数。这使我可以毫无问题地将所有内容都放入 refcursor。

虽然这可能性能不佳(循环游标并手动聚合),但这是针对月度报告的,因此在必要之前我不会尝试优化(因为我们还有其他工作要做)。

【讨论】:

以上是关于打开 PL/SQL 语句的引用器?的主要内容,如果未能解决你的问题,请参考以下文章

Oracle | PL/SQL编程

PL/Sql快速执行 insert语句的.sql文件

利用pl/sql执行计划评估SQL语句的性能简析

PL/SQL编程_游标

Excel 通过pl/sql导入到数据库 文本导入器 odbc导入器

如何从 Oracle 10G PL/SQL 函数和过程中查找所有表引用? [复制]