PL/SQL中如何在子循环内再次遍历游标实现记录对比?
解决PL/SQL中游标重复遍历对比记录的问题
普通游标只能单向读取一次,无法在主循环内重复遍历。要实现每条预约记录互相对比,最有效的方式是把游标结果一次性存入内存集合,之后就可以多次遍历集合完成对比操作,比嵌套查询效率提升明显。
以下是修改后的完整代码,关键部分已添加注释:
FUNCTION RES_DETP (P_OBJET IN NUMBER ,P_DATE_DEBUT IN DATE ,P_DATE_FIN IN DATE ,P_SOCIETE IN VARCHAR2 ) RETURN BOOLEAN IS -- 1. 定义基于游标行类型的嵌套表类型 TYPE T_RESERVATION_LIST IS TABLE OF LISTE_RESERVATION%ROWTYPE; -- 2. 声明集合变量存储所有预约记录 V_RES_LIST T_RESERVATION_LIST; CURSOR LISTE_RESERVATION IS SELECT NOM cur_nom, PRENOM cur_prenom, RESERVATIONS.DATE_DEBUT_PRECIS cur_ddp, RESERVATIONS.DATE_FIN_PRECIS cur_dfp FROM CLIENTS,RESERVATIONS,LIGNES_RESERVATIONS WHERE LIGNES_RESERVATIONS.OBJ_NUMERO = P_OBJET AND LIGNES_RESERVATIONS.OBJ_SOCIETES_ID = P_SOCIETE AND LIGNES_RESERVATIONS.SOCIETES_ID = P_SOCIETE AND RESERVATIONS.SOCIETES_ID = P_SOCIETE AND LIGNES_RESERVATIONS.RES_NUMERO = RESERVATIONS.NUMERO AND LIGNES_RESERVATIONS.RES_SOCIETES_ID = RESERVATIONS.SOCIETES_ID AND CLIENTS.NUMERO = RESERVATIONS.CLI_NUMERO AND CLIENTS.SOCIETES_ID = RESERVATIONS.CLI_SOCIETES_ID AND CLIENTS.SOCIETES_ID = P_SOCIETE AND P_DATE_FIN > DATE_DEBUT_PRECIS AND P_DATE_DEBUT < DATE_FIN_PRECIS ORDER BY RESERVATIONS.DATE_DEBUT_PRECIS; BEGIN -- 3. 批量读取游标所有数据到集合,随后关闭游标 OPEN LISTE_RESERVATION; FETCH LISTE_RESERVATION BULK COLLECT INTO V_RES_LIST; CLOSE LISTE_RESERVATION; -- 4. 嵌套循环遍历集合,执行记录对比 FOR I IN V_RES_LIST.FIRST .. V_RES_LIST.LAST LOOP -- 主循环当前记录 FOR J IN V_RES_LIST.FIRST .. V_RES_LIST.LAST LOOP -- 可选:跳过自身对比,根据实际需求调整 IF I = J THEN CONTINUE; END IF; -- 这里写入你的对比逻辑,示例为检查时间重叠 IF V_RES_LIST(I).cur_ddp < V_RES_LIST(J).cur_dfp AND V_RES_LIST(I).cur_dfp > V_RES_LIST(J).cur_ddp THEN -- 找到符合条件的记录,返回TRUE(示例逻辑) RETURN TRUE; END IF; END LOOP; END LOOP; -- 未找到符合条件的记录,返回FALSE RETURN FALSE; END;
关键说明
- 使用
BULK COLLECT INTO一次性加载游标数据到集合,比逐行FETCH效率更高,适合处理大量数据 - 集合存储在内存中,支持任意次数的遍历,完美满足重复对比的需求
- 如果数据量极大(如上万条),可添加
LIMIT分批加载避免内存溢出,示例:FETCH LISTE_RESERVATION BULK COLLECT INTO V_RES_LIST LIMIT 1000;,然后循环加载直到游标为空 - 对比逻辑可根据实际业务需求自由调整,比如修改对比字段、调整判断规则等
内容的提问来源于stack exchange,提问作者DanisOnTheFlux
相关产品推荐
相关产品推荐

