PL/SQL嵌套显式游标查询2007夏季学期选课名单输出异常求助
问题排查与修复方案
核心错误原因
你的两个游标完全独立,内层S_NAME游标没有绑定外层循环取出的具体课程段条件,所以每次内层循环都会输出2007年夏季学期所有选课的学生,而不是当前外层遍历的那门课程的选课名单,完全没有关联逻辑,自然无法输出对应结果。
修复方案
我们需要改成带参数的内层游标,把外层循环拿到的课程段主键C_SEC_ID传递给内层游标,过滤出对应课程的学生即可。修改后的完整代码如下:
SET SERVEROUTPUT ON SIZE 4000; DECLARE v_call_id COURSE.CALL_ID%TYPE; v_sec_num COURSE_SECTION.SEC_NUM%TYPE; v_c_sec_id COURSE_SECTION.C_SEC_ID%TYPE; -- 新增存储课程段主键的变量 v_fname STUDENT.S_FIRST%TYPE ; v_lname STUDENT.S_LAST%TYPE; -- 外层游标:查询2007夏季学期所有课程的课程段ID、课程号、课程序号 CURSOR c_info is SELECT c.CALL_ID, cs.SEC_NUM, cs.C_SEC_ID FROM COURSE_SECTION cs JOIN COURSE c ON cs.COURSE_ID = c.COURSE_ID JOIN TERM t ON cs.TERM_ID = t.TERM_ID WHERE t.TERM_DESC = 'Summer 2007' ; -- 带参数的内层游标:接收外层传入的课程段ID,查询对应课程段的选课学生 CURSOR S_NAME(p_c_sec_id COURSE_SECTION.C_SEC_ID%TYPE) IS SELECT DISTINCT s.S_FIRST, s.S_LAST FROM STUDENT s JOIN ENROLLMENT e ON s.S_ID = e.S_ID WHERE e.C_SEC_ID = p_c_sec_id; -- 仅查询当前课程段的学生 BEGIN OPEN c_info; LOOP FETCH c_info INTO v_call_id, v_sec_num, v_c_sec_id; EXIT WHEN c_info%NOTFOUND; DBMS_OUTPUT.PUT_LINE('=================================='); DBMS_OUTPUT.PUT_LINE(v_call_id || ' Sec. ' || v_sec_num); DBMS_OUTPUT.PUT_LINE('=================================='); -- 打开内层游标时传入当前课程段的ID OPEN S_NAME(v_c_sec_id); LOOP FETCH S_NAME INTO v_fname, v_lname; EXIT WHEN S_NAME%NOTFOUND; DBMS_OUTPUT.PUT_LINE(v_fname || ' ' || v_lname ); END LOOP; CLOSE S_NAME ; END LOOP; CLOSE c_info; END; /
额外优化说明
- 用JOIN语法替代老式的逗号连接表,可读性更强,避免漏写关联条件
- 变量名加前缀
v_和字段名做区分,避免命名冲突 - 内层游标去掉了冗余的
COURSE_SECTION、TERM表关联,直接通过传入的课程段ID过滤,执行效率更高
内容的提问来源于stack exchange,提问作者Muha18
相关产品推荐
相关产品推荐

