一、游标FOR循环

游标FOR循环处理显式游标中的行。 这是一个快捷方式,因为游标被打开,循环中的每次迭代都会获取一次行,当处理最后一行时会退出循环,并且游标会自动关闭。 当最后一行被提取时,循环本身在迭代结束时自动终止。

(1)语法

FOR record_name IN cursor_name LOOP
 statement1;
 statement2;
 . . .
END LOOP;

在语法中:


•record_name是隐式声明的记录的名称(作为cursor_name%ROWTYPE)


•cursor_name是先前声明的游标的PL / SQL标识符

注意:v_emp_record是隐式声明的记录。 

(2)隐式记录访问

可以使用此隐式记录访问获取的数据, 通过使用INTO子句,没有声明变量来保存获取的数据。 该代码没有OPEN和CLOSE语句分别打开和关闭游标。

DECLARE
 CURSOR emp_cursor IS
 SELECT employee_id, last_name FROM employees
 WHERE department_id = 50;
BEGIN
 FOR v_emp_record IN emp_cursor
 LOOP
 DBMS_OUTPUT.PUT_LINE(v_emp_record.employee_id
 || ' ' ||v_emp_record.last_name);
 END LOOP;
END;

(3)游标FOR循环比较

将游标FOR循环代码与您在前一文中学到的展开代码进行比较。 这两种形式的代码在逻辑上彼此相同,并产生完全相同的结果。

DECLARE
 CURSOR emp_cursor IS
 SELECT employee_id, last_name
FROM employees
 WHERE department_id = 50;
BEGIN
 FOR v_emp_record IN emp_cursor
 LOOP
 DBMS_OUTPUT.PUT_LINE(…);
 END LOOP;
END;
DECLARE
 CURSOR emp_cursor IS
 SELECT employee_id, last_name
 FROM employees
 WHERE department_id = 50;
 v_emp_record emp_cursor%ROWTYPE;
BEGIN
 OPEN emp_cursor;
 LOOP
 FETCH emp_cursor INTO
 v_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。 它包含多少个字段?

DECLARE
 CURSOR dept_cursor IS
 SELECT department_id, department_name
 FROM departments
 ORDER BY department_id;
BEGIN
 FOR v_dept_record IN dept_cursor
 LOOP
 DBMS_OUTPUT.PUT_LINE( v_dept_record.department_id
 || ' ' ||v_dept_record.department_name);
 END LOOP;
END;


二、循环游标准则

(1)指南

•不要声明控制循环的记录,因为它是隐式声明的。


•隐式记录的范围仅限于循环,因此无法在循环外引用记录。


•您可以通过record_name.column_name访问获取的数据。

(2)测试游标属性

您仍然可以测试游标属性,例如%ROWCOUNT。 在取出并处理了五行后,此示例从循环中退出。 光标自动关闭。


DECLARE
 CURSOR emp_cursor IS
 SELECT employee_id, last_name FROM employees;
BEGIN
 FOR v_emp_record IN emp_cursor
 LOOP
 EXIT 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子句在技术上是一个子查询,因此您必须将其放在括号中。


BEGIN
 FOR v_emp_record IN (SELECT employee_id, last_name
 FROM employees WHERE department_id =50)
 LOOP
 DBMS_OUTPUT.PUT_LINE(v_emp_record.employee_id
 ||' '||v_emp_record.last_name);
 END LOOP;
END;

再次,比较这两种形式的代码。 它们在逻辑上是相同的。 但是你宁愿写哪一个?

BEGIN
 FOR v_dept_rec IN (SELECT *
 FROM departments)
 LOOP
 DBMS_OUTPUT.PUT_LINE(…);
 END LOOP;
END;
DECLARE
 CURSOR dept_cursor IS
 SELECT * FROM departments;
 v_dept_rec
dept_cursor%ROWTYPE;
BEGIN
 OPEN dept_cursor;
 LOOP
 FETCH dept_cursor INTO
 v_dept_rec;
 EXIT WHEN
dept_cursor%NOTFOUND;
 DBMS_OUTPUT.PUT_LINE(…);
 END LOOP;
 CLOSE dept_cursor;
END;