一、游标FOR循环
游标FOR循环处理显式游标中的行。 这是一个快捷方式,因为游标被打开,循环中的每次迭代都会获取一次行,当处理最后一行时会退出循环,并且游标会自动关闭。 当最后一行被提取时,循环本身在迭代结束时自动终止。
(1)语法
FOR record_name IN cursor_name LOOPstatement1;statement2;. . .
END LOOP;
在语法中:
•record_name是隐式声明的记录的名称(作为cursor_name%ROWTYPE)
•cursor_name是先前声明的游标的PL / SQL标识符
注意:v_emp_record是隐式声明的记录。
(2)隐式记录访问
可以使用此隐式记录访问获取的数据, 通过使用INTO子句,没有声明变量来保存获取的数据。 该代码没有OPEN和CLOSE语句分别打开和关闭游标。
DECLARECURSOR emp_cursor ISSELECT employee_id, last_name FROM employeesWHERE department_id = 50;
BEGINFOR v_emp_record IN emp_cursorLOOPDBMS_OUTPUT.PUT_LINE(v_emp_record.employee_id|| ' ' ||v_emp_record.last_name);END LOOP;
END;
(3)游标FOR循环比较
将游标FOR循环代码与您在前一文中学到的展开代码进行比较。 这两种形式的代码在逻辑上彼此相同,并产生完全相同的结果。
DECLARECURSOR emp_cursor ISSELECT employee_id, last_name
FROM employeesWHERE department_id = 50;
BEGINFOR v_emp_record IN emp_cursorLOOPDBMS_OUTPUT.PUT_LINE(…);END LOOP;
END;
DECLARECURSOR emp_cursor ISSELECT employee_id, last_nameFROM employeesWHERE department_id = 50;v_emp_record emp_cursor%ROWTYPE;
BEGINOPEN emp_cursor;LOOPFETCH emp_cursor INTOv_emp_record;EXIT WHEN emp_cursor%NOTFOUND;DBMS_OUTPUT.PUT_LINE(…);END LOOP;CLOSE emp_cursor;
END;
(4)游标FOR循环:第二个例子
已将v_dept_record隐式声明为dept_cursor%ROWTYPE。 它包含多少个字段?DECLARECURSOR dept_cursor ISSELECT department_id, department_nameFROM departmentsORDER BY department_id;
BEGINFOR v_dept_record IN dept_cursorLOOPDBMS_OUTPUT.PUT_LINE( v_dept_record.department_id|| ' ' ||v_dept_record.department_name);END LOOP;
END;
二、循环游标准则
(1)指南
•不要声明控制循环的记录,因为它是隐式声明的。•隐式记录的范围仅限于循环,因此无法在循环外引用记录。
•您可以通过record_name.column_name访问获取的数据。
(2)测试游标属性
您仍然可以测试游标属性,例如%ROWCOUNT。 在取出并处理了五行后,此示例从循环中退出。 光标自动关闭。DECLARECURSOR emp_cursor ISSELECT employee_id, last_name FROM employees;
BEGINFOR v_emp_record IN emp_cursorLOOPEXIT WHEN emp_cursor%ROWCOUNT > 5;DBMS_OUTPUT.PUT_LINE( v_emp_record.employee_id|| ' ' ||v_emp_record.last_name);END LOOP;
END;
(3)游标FOR循环使用子查询
你可以更进一步。 你根本不需要声明游标! 相反,您可以直接在FOR循环中指定光标所基于的SELECT。 这样做的好处是所有的游标定义都包含在一个FOR ...语句中。 这使代码的后续更改变得更加容易和快速。
例子
FOR语句中的SELECT子句在技术上是一个子查询,因此您必须将其放在括号中。BEGINFOR v_emp_record IN (SELECT employee_id, last_nameFROM employees WHERE department_id =50)LOOPDBMS_OUTPUT.PUT_LINE(v_emp_record.employee_id||' '||v_emp_record.last_name);END LOOP;
END;
再次,比较这两种形式的代码。 它们在逻辑上是相同的。 但是你宁愿写哪一个?
BEGINFOR v_dept_rec IN (SELECT *FROM departments)LOOPDBMS_OUTPUT.PUT_LINE(…);END LOOP;
END;
DECLARECURSOR dept_cursor ISSELECT * FROM departments;v_dept_rec
dept_cursor%ROWTYPE;
BEGINOPEN dept_cursor;LOOPFETCH dept_cursor INTOv_dept_rec;EXIT WHEN
dept_cursor%NOTFOUND;DBMS_OUTPUT.PUT_LINE(…);END LOOP;CLOSE dept_cursor;
END;