一、游标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;