重构 PL/SQL:许多具有相同行类型的游标(理论上)
我正在编写一些 PL/SQL,发现自己陷入了重复模式:
cursor c_curs1 is
select a, b, c
from (...) big_subquery_1
where big_subquery_1.a_ind = 'Y'
cursor c_curs2 is
select a, b, c
from (...) big_subquery_2
where big_subquery_2.b_ind = 'R'
cursor c_curs3 is
select a, b, c
from (...) big_subquery_3
where big_subquery_3.c_ind = 'M'
...
type t_curs1_tab is table of c_curs1;
type t_curs2_tab is table of c_curs2;
type t_curs3_tab is table of c_curs3;
...
v_curs1_results t_curs1_tab := t_curs1_tab();
v_curs2_results t_curs2_tab := t_curs2_tab();
v_curs3_results t_curs3_tab := t_curs3_tab();
然后在处理结果时,我有这样的代码:
open c_curs1;
fetch c_curs1 bulk collect into v_curs1_results;
close c_curs1;
if v_curs1_results.first is not null and v_curs1_results.last is not null then
for i in v_curs1_results.first .. v_curs1_results.last loop
/*Do something with field a in the results
Do something with field b in the results
Do something with field c in the results*/
....
end loop;
end if;
处理循环中的代码对于所有游标都是相同的,因为所有 3 个游标都返回 a ,b,c
- 唯一的区别是引用哪个光标。我想将其重构为某种通用结果集处理器,但我被困在这里:
procedure sp_process_collection(in_collection t_curs1_tab) is ...
我只能用 v_curs1_results
调用它,不能用 v_curs2_results
调用它code> 或我收到 PLS-00306 类型或参数数量错误...
编译器错误。有没有什么办法可以通用地做到这一点,这样我只需要编写一个集合处理过程?我有这种光标模式(返回相同的三列,始终相同的类型)出现在同一包和处理循环的其他几个部分中,而语义上相同的有时用稍微不同的代码编写。我非常想将处理集中在一个过程中,我只是知道如何在 PL/SQL 中做到这一点。我知道 PL/SQL 没有泛型(我认为这会使 Java/C# 解决方案变得相当微不足道),但我想知道是否有另一种方法可以解决这个我刚刚没有的问题没想到。
(使用Oracle 10g)
I am writing some PL/SQL and found myself falling into a repeptitive pattern:
cursor c_curs1 is
select a, b, c
from (...) big_subquery_1
where big_subquery_1.a_ind = 'Y'
cursor c_curs2 is
select a, b, c
from (...) big_subquery_2
where big_subquery_2.b_ind = 'R'
cursor c_curs3 is
select a, b, c
from (...) big_subquery_3
where big_subquery_3.c_ind = 'M'
...
type t_curs1_tab is table of c_curs1;
type t_curs2_tab is table of c_curs2;
type t_curs3_tab is table of c_curs3;
...
v_curs1_results t_curs1_tab := t_curs1_tab();
v_curs2_results t_curs2_tab := t_curs2_tab();
v_curs3_results t_curs3_tab := t_curs3_tab();
Then when processing the results, I have code like this:
open c_curs1;
fetch c_curs1 bulk collect into v_curs1_results;
close c_curs1;
if v_curs1_results.first is not null and v_curs1_results.last is not null then
for i in v_curs1_results.first .. v_curs1_results.last loop
/*Do something with field a in the results
Do something with field b in the results
Do something with field c in the results*/
....
end loop;
end if;
The code in the processing loop is the same for all cursors, as all 3 cursors return a,b,c
- the only difference being which cursor is referenced. I wanted to refactor this into some sort of generic result-set processor, but I'm stuck here:
procedure sp_process_collection(in_collection t_curs1_tab) is ...
I can only call this with v_curs1_results
, I can't call it with v_curs2_results
or I get a PLS-00306 wrong number of types or arguments...
compiler error. Is there any way to do this generically so I only have to write one collection processing procedure? I have this pattern of cursor (returning the same three columns, always the same types) appears in several other parts of the same package, and the processing loop, while semantically the same is sometimes written with slightly different code. I'd very much like to centralize the processing in one procedure, I just can'd figure out how to do it in PL/SQL. I know PL/SQL doesn't have generics (Which I think would have made a Java/C# solution fairly trivial), but I'm wondering if there's another way to approach this problem that I just haven't thought of.
(using Oracle 10g)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果结果列相同,则没有理由使用三个 TYPE 声明。你只有一种类型。您是否需要该类型的一个或多个变量取决于您是否需要同时保存不同的数据集。
If the resulting columns are the same, there's no reason to have three TYPE declarations. You just have one TYPE. Whether you need one or more variables of that TYPE depends on whether you need to hold the different data sets concurrently.
如果您愿意并且被允许这样做,您可以创建一个
TYPE
来表示任何游标返回的记录。例如:还有另一种类型来保存
TRIPLE_TYPE
的集合:最后,定义游标以返回
TRIPLE_TYPE
记录:此技术允许您编写一个接受
TRIPLE_TYPE
的过程。代码>TRIPLES_TYPE集合:If you are willing and permitted to do so, you can create a
TYPE
to represent a record returned by any of the cursors. For example:And another type to hold a collection of
TRIPLE_TYPE
:Finally, you define your cursors to return
TRIPLE_TYPE
records:This technique allows you to write a procedure that accepts a
TRIPLES_TYPE
collection:您可以使用 REF CURSOR 来完成此操作吗?
类似于:
您的调用代码需要每个游标调用此过程一次:
Can you do this with a REF CURSOR?
Something like:
Your calling code would need to invoke this procedure once per cursor:
看起来你必须有 3 个游标,因为我认为每个游标中的“big_subquery”都是不同的。因此,您实际上只需要集中一个过程来处理 a、b 和 c 结果。这里没什么太花哨的,只需定义一个本地过程来执行此操作:
当然,如果您需要为每行一起处理所有 3 种类型,或者类型不同(varchar2、日期和数字),只需修改 process_type 过程传递所有 3 个(a、b 和 c)。例如:
如果您需要返回值,您可以将其设为函数。
Seems like you HAVE to have 3 cursors because the "big_subquery" in each are different I assume. So, you really just need to centralize a procedure to handle processing a, b, and c results. Nothing too fancy here, just define a local procedure to do this:
Of course, if you need to process all 3 types together for each row, or if the types are different (varchar2, date, and number), just modify the process_type procedure to pass in all 3 (a,b,and c). Something like:
And you can make this a function if you need a return value.