如何修复PL/SQL遍历Territory计算销售额时重复循环的问题
问题修复:PL/SQL循环Territory计算总销售额重复同一数据
你的代码核心问题有两个:
- 内层游标
CURSOR_2查询了所有Territory的订单明细,每次外层循环打开游标后会把所有记录遍历完,最终TERRITORY_ID和TERRITORY_DESC会停在最后一条记录的值,导致每次输出都是同一个Territory的数据。 - 外层循环的
T.TERRITORYID完全没起到过滤作用,内层游标没有关联当前循环的Territory,等于白遍历了外层的Territory列表。
修复方案一:带参数的游标(贴合你的循环思路)
把内层游标改成带参数的形式,每次只查询当前Territory的订单明细,让内外循环关联起来:
DECLARE TERRITORY_ID NUMBER(5); TERRITORY_DESC VARCHAR(50); NUMBER_SOLD NUMBER(5); UNIT_PRICE NUMBER(10); SUBTOTAL NUMBER(10); TOTAL NUMBER(10) := 0; -- 定义带参数的游标,接收当前TerritoryID做过滤 CURSOR CURSOR_2(p_territory_id NUMBER) IS SELECT T.TERRITORYID, T.TERRITORYDESCRIPTION, OD.QUANTITY, OD.UNITPRICE FROM TERRITORIES T JOIN ORDERS O ON T.TERRITORYID = O.TERRITORYID JOIN ORDERDETAILS OD ON O.ORDERID = OD.ORDERID WHERE T.TERRITORYID = p_territory_id; BEGIN DBMS_OUTPUT.put_line('TERRITORY_ID' || '|' || 'TERRITORY_DESC' || '|' || 'TOTAL'); -- 外层循环遍历所有Territory FOR t_rec IN (SELECT TERRITORYID, TERRITORYDESCRIPTION FROM TERRITORIES) LOOP TOTAL := 0; -- 打开游标时传入当前TerritoryID OPEN CURSOR_2(t_rec.TERRITORYID); LOOP FETCH CURSOR_2 INTO TERRITORY_ID, TERRITORY_DESC, NUMBER_SOLD, UNIT_PRICE; EXIT WHEN CURSOR_2%NOTFOUND; SUBTOTAL := NUMBER_SOLD * UNIT_PRICE; TOTAL := TOTAL + SUBTOTAL; END LOOP; CLOSE CURSOR_2; -- 输出当前Territory的统计结果 DBMS_OUTPUT.put_line(t_rec.TERRITORYID || '|' || t_rec.TERRITORYDESCRIPTION || '|' || TOTAL); END LOOP; END; /
修复方案二:直接用SQL聚合(更高效,推荐)
其实完全不需要嵌套游标,用SQL的GROUP BY就能直接完成聚合计算,代码更简洁且性能更好:
BEGIN DBMS_OUTPUT.put_line('TERRITORY_ID' || '|' || 'TERRITORY_DESC' || '|' || 'TOTAL'); FOR rec IN ( SELECT T.TERRITORYID, T.TERRITORYDESCRIPTION, SUM(OD.QUANTITY * OD.UNITPRICE) AS TOTAL_SALES FROM TERRITORIES T JOIN ORDERS O ON T.TERRITORYID = O.TERRITORYID JOIN ORDERDETAILS OD ON O.ORDERID = OD.ORDERID GROUP BY T.TERRITORYID, T.TERRITORYDESCRIPTION ) LOOP DBMS_OUTPUT.put_line(rec.TERRITORYID || '|' || rec.TERRITORYDESCRIPTION || '|' || rec.TOTAL_SALES); END LOOP; END; /
额外优化说明
- 用显式
JOIN代替老式逗号分隔表的写法,代码可读性更强。 - 方案二利用数据库原生聚合函数,比游标循环的计算效率高很多,数据量越大优势越明显。
内容的提问来源于stack exchange,提问作者victor leung
相关产品推荐
相关产品推荐

