【发布时间】:2020-07-15 07:05:35
【问题描述】:
我想知道是否有办法附加到从循环内部获取的游标的结果。
现在 out_cursor 包含与外部 for 循环的最后一次迭代有关的结果。我想知道是否可以将每次迭代中的行附加到此游标中,以便游标包含来自循环的所有迭代的行。
对于上下文,此 out_cursor 由 Java DAO 类使用。
CREATE OR REPLACE NONEDITIONABLE PROCEDURE testproc (out_cursor OUT SYS_REFCURSOR)
IS
CURSOR actor_cursor IS
SELECT actor_id, first_name, last_name
FROM actor
WHERE actor_id <= 100;
row1 actor_cursor%rowtype;
TYPE MyRec IS RECORD (actor_id film_actor.actor_id%TYPE, film_id film_actor.film_id%TYPE);
rec MyRec;
BEGIN
FOR row1 IN actor_cursor
LOOP
dbms_output.put_line('actor_id:'||row1.actor_id ||' ---- '|| row1.first_name || row1.last_name);
OPEN out_cursor FOR
SELECT actor_id, film_id
FROM film_actor
WHERE actor_id = row1.actor_id;
END LOOP;
LOOP -- this loop is here just to print out_cursor for testing
FETCH out_cursor INTO rec;
EXIT WHEN out_cursor%NOTFOUND;
dbms_output.put_line('actor_id:'||rec.actor_id||', film_id:'||rec.film_id);
END LOOP;
END;
脚本的输出是这样的
actor_id:98 ---- CHRIS BRIDGES
actor_id:99 ---- JIM MOSTEL
actor_id:100 ---- SPENCER DEPP
actor_id:100, film_id:17
actor_id:100, film_id:118
我知道只有来自 for 循环最后一次迭代的行在 out_cursor 中。
有什么办法可以让out_cursor返回外层FOR LOOP所有迭代的结果,本质上是聚合所有迭代的结果。产生这样的结果?
actor_id:98 ---- CHRIS BRIDGES
actor_id:99 ---- JIM MOSTEL
actor_id:100 ---- SPENCER DEPP
actor_id:98, film_id:77 // results from iteration #1
actor_id:98, film_id:43
actor_id:99, film_id:67 // results from iteration #2
actor_id:99, film_id:90
actor_id:100, film_id:17 // results from iteration #3
actor_id:100, film_id:118
我知道我可以使用 JOINS 轻松归档相同的结果。但是我不能修改 SQL 查询(实际的 SQL 非常复杂)——我只能运行它们并将一个 SQL 产生的结果用作下一个 SQL 的参数(在 SELECT 或 WHERE 子句中)。
(更新) 一般要求是 - 有一系列查询,每个查询的结果集用于下一个的约束。我不能自己修改查询 - 所以使用连接或子查询是不可能的。
我希望为每个查询打开一个游标,然后遍历游标中的值 - 使用下一个查询的约束中的游标属性,为此我将在 for 循环中打开一个游标。完全如示例中所示。但问题是循环内的光标只包含上次迭代中所做的选择——在每次迭代期间,都会创建一个新的光标。所以,我在 out_cursor 中只得到了我想要的结果的一个子集。
我想我找到了一种方法来做到这一点 -
CREATE OR REPLACE PACKAGE PKG_BIDS_REPORTS_TEST as
TYPE Q2DATA IS RECORD (
actor_id film_actor.actor_id%TYPE,
film_id film_actor.film_id%TYPE
);
TYPE Q2DATA_TAB IS TABLE OF Q2DATA INDEX BY BINARY_INTEGER;
Q2DATA_REC Q2DATA_TAB;
PROCEDURE pqr_reports_test(l_out_data OUT sys_refcursor);
end PKG_BIDS_REPORTS_TEST;
/
create or replace NONEDITIONABLE PACKAGE BODY PKG_BIDS_REPORTS_TEST as
PROCEDURE pqr_reports_test(l_out_data OUT sys_refcursor) AS
CURSOR actor_cursor IS
SELECT actor_id, first_name, last_name
FROM actor
WHERE actor_id <= 100;
row1 actor_cursor%rowtype;
CURSOR film_actor_cursor(actorid film_actor.actor_id%TYPE) IS
SELECT actor_id, film_id
FROM film_actor
WHERE actor_id = actorid;
row2 film_actor_cursor%rowtype;
V_CNT NUMBER:=0;
BEGIN
V_CNT := q2data_rec.COUNT;
FOR row1 IN actor_cursor
LOOP
--dbms_output.put_line(row1.actor_id ||' ---- '|| row1.first_name ||' ---- '|| row1.last_name);
FOR row2 IN film_actor_cursor(row1.actor_id)
LOOP
V_CNT := V_CNT + 1;
q2data_rec(V_CNT).actor_id := row2.actor_id;
q2data_rec(V_CNT).film_id := row2.film_id;
--dbms_output.put_line(row2.actor_id||','||row2.film_id);
END LOOP;
END LOOP;
OPEN L_OUT_DATA FOR SELECT DISTINCT datarec.actor_id, datarec.film_id from TABLE(q2data_rec) datarec;
END;
End PKG_BIDS_REPORTS_TEST;
本质上是创建一个 PLSQL 表并在循环中填充一个像 Java 数组这样的计数器。有用。绝对不是最优雅的。
因此,我绝对会感谢任何优化或替代方案。
【问题讨论】:
-
没有办法扩展游标的内容。游标包含 SINGLE 选择语句的结果。见here。请提供您正在尝试的完整示例,可能类似于minimal reproducible example 和完整示例数据(另请参阅How to Ask)。然后社区才能提供满意的答案。
标签: oracle plsql append cursor