游標分類總覽
| 類型 | 建立時機 | 名稱 | 適用場景 | 關鍵特性 |
| 隱式游標 | DML/SELECT INTO 執行時自動 | 固定 SQL | 單行 DML/查詢 | 屬性 %FOUND/%NOTFOUND/%ROWCOUNT/%ISOPEN |
| 顯式游標 | 宣告區 CURSOR c IS ... | 自訂 | 多行查詢、需精確控制 | OPEN/FETCH/CLOSE、FOR LOOP、WHERE CURRENT OF |
| REF 游標 | 執行期 OPEN c FOR sql | 游標變數 | 動態 SQL、跨子程序傳遞 | 強/弱類型、可作為 OUT 參數返回 |
一、隱式游標
DECLARE
v_name student.sname%TYPE;
CURSOR c_stu IS SELECT sname FROM student;
BEGIN
OPEN c_stu;
FETCH c_stu INTO v_name;
WHILE c_stu%FOUND LOOP
DBMS_OUTPUT.PUT_LINE('學生:' || v_name);
FETCH c_stu INTO v_name;
END LOOP;
CLOSE c_stu;
END;
2. 參數化游標
DECLARE
CURSOR c_stu IS SELECT * FROM student;
BEGIN
FOR r IN c_stu LOOP
DBMS_OUTPUT.PUT_LINE('學號:'||r.sno||' 姓名:'||r.sname);
-- 無需 OPEN/FETCH/CLOSE,自動處理
END LOOP;
END;
4. WHERE CURRENT OF 更新當前行
DECLARE
CURSOR c_emp IS SELECT ename FROM emp WHERE deptno=10;
TYPE ename_tab IS TABLE OF VARCHAR2(10);
v_names ename_tab;
BEGIN
OPEN c_emp;
FETCH c_emp BULK COLLECT INTO v_names;
FOR i IN 1..v_names.COUNT LOOP DBMS_OUTPUT.PUT_LINE(v_names(i)); END LOOP;
CLOSE c_emp;
END;
三、實戰綜合案例:跨表游標同步更新
DECLARE
TYPE ref_cur IS REF CURSOR;
c_ref ref_cur;
v_name student.sname%TYPE;
v_no student.sno%TYPE;
v_tab VARCHAR2(20) := '&表名';
BEGIN
IF v_tab = 'student' THEN
OPEN c_ref FOR SELECT sno, sname FROM student;
FETCH c_ref INTO v_no, v_name;
WHILE c_ref%FOUND LOOP
DBMS_OUTPUT.PUT_LINE('學號:'||v_no||' 姓名:'||v_name);
FETCH c_ref INTO v_no, v_name;
END LOOP;
CLOSE c_ref;
ELSE
DBMS_OUTPUT.PUT_LINE('無此表');
END IF;
END;
2. 實戰:彙總學生選課記錄到單行