如何在游标c_employees内部声明接收其返回employees_id参数的嵌套游标
嵌套游标传参实现方案
你原来的写法报错的核心原因是 PL/SQL的游标必须声明在DECLARE块中,不能直接写在执行逻辑的BEGIN/END块内,要实现外层游标值传入内层游标作为查询条件,有两种可行方案,优先推荐参数化游标写法:
方案1:预定义带参数的内层游标(推荐)
提前在最外层声明段定义好带参数的内层游标,遍历的时候直接传入外层游标获取到的employee_id即可,性能更优,逻辑更清晰:
DECLARE -- 外层游标:查询所有员工ID CURSOR c_employees IS SELECT employees_id FROM employees; -- 定义带参数的内层游标:参数p_emp_id用于接收传入的员工ID CURSOR c_leaves(p_emp_id NUMBER) IS SELECT hours FROM my_table WHERE employees_id = p_emp_id; BEGIN -- 遍历外层游标取每个员工ID FOR e IN c_employees LOOP -- 遍历内层游标,传入当前员工ID作为查询条件 FOR j IN c_leaves(e.employees_id) LOOP -- 你的插入逻辑 INSERT INTO table2(/* 对应字段 */) VALUES (/* 对应赋值 */); END LOOP; END LOOP; -- 提交事务 COMMIT; EXCEPTION WHEN OTHERS THEN -- 异常回滚 ROLLBACK; RAISE; END; /
方案2:内层块声明游标
如果确实有需求要把内层游标写在循环内部,可以给内层逻辑块增加DECLARE声明段,写法如下:
DECLARE CURSOR c_employees IS SELECT employees_id FROM employees; BEGIN FOR e IN c_employees LOOP -- 内层块单独加DECLARE段声明对应游标 DECLARE CURSOR c_leaves IS SELECT hours FROM my_table WHERE employees_id = e.employees_id; BEGIN FOR j IN c_leaves LOOP INSERT INTO table2(/* 对应字段 */) VALUES (/* 对应赋值 */); END LOOP; END; END LOOP; COMMIT; EXCEPTION WHEN OTHERS THEN ROLLBACK; RAISE; END; /
额外优化提示:如果你的业务只是关联两张表做插入操作,完全不需要写嵌套游标,单条关联插入SQL的性能远高于游标遍历:
INSERT INTO table2(/* 对应字段 */) SELECT /* 对应字段 */ FROM employees e JOIN my_table m ON e.employees_id = m.employees_id;
内容的提问来源于stack exchange,提问作者Pointer
相关产品推荐
相关产品推荐

