打开 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 语句的引用器?的主要内容,如果未能解决你的问题,请参考以下文章