游標生命週期六階段
PARSE 解析
BIND 綁定變數
OPEN 開啟游標
EXECUTE 執行
FETCH 擷取資料
CLOSE 關閉游標
隱性游標四大屬性
| 屬性 | 含義 | 回傳值 |
%FOUND | 最近 FETCH 是否取得資料列 | TRUE / FALSE |
%NOTFOUND | 最近 FETCH 未取得資料列 | TRUE / FALSE |
%ROWCOUNT | 累計擷取資料列數 | NUMBER |
%ISOPEN | 游標是否開啟 | TRUE / FALSE |
基本游標範例
DECLARE
CURSOR c_tables IS SELECT * FROM user_tables;
rec c_tables%ROWTYPE;
BEGIN
OPEN c_tables;
FETCH c_tables INTO rec;
WHILE c_tables%FOUND LOOP
DBMS_OUTPUT.PUT_LINE(rec.table_name);
FETCH c_tables INTO rec;
END LOOP;
CLOSE c_tables;
END;
%NOTFOUND 替代寫法
OPEN c_tables;
FETCH c_tables INTO rec;
WHILE c_tables%FOUND LOOP
EXIT WHEN c_tables%NOTFOUND; -- 等同於 NOT FOUND 判斷
FETCH c_tables INTO rec;
END LOOP;
CLOSE c_tables;
%ROWCOUNT 統計範例
OPEN c_tables;
FETCH c_tables INTO rec;
WHILE c_tables%FOUND LOOP
DBMS_OUTPUT.PUT_LINE('已讀取 ' || c_tables%ROWCOUNT || ' 筆');
FETCH c_tables INTO rec;
END LOOP;
CLOSE c_tables;
%ISOPEN 檢查範例
DECLARE
CURSOR c_tables IS SELECT * FROM user_tables;
BEGIN
IF c_tables%ISOPEN THEN
DBMS_OUTPUT.PUT_LINE('Cursor already open');
ELSE
OPEN c_tables;
END IF;
CLOSE c_tables;
END;
帶參數游標
DECLARE
CURSOR c_admin(p_id NUMBER) IS SELECT * FROM admin WHERE id = p_id;
BEGIN
OPEN c_admin(10);
-- FETCH ...
CLOSE c_admin;
END;
FOR UPDATE 鎖定列
DECLARE
CURSOR c_lock IS SELECT id FROM admin FOR UPDATE OF id;
BEGIN
OPEN c_lock;
-- 處理邏輯
COMMIT; -- 或 ROLLBACK 釋放鎖
CLOSE c_lock;
END;
WHERE CURRENT OF 定位更新/刪除
UPDATE admin SET status = 'processed' WHERE CURRENT OF c_lock;
DELETE FROM admin WHERE CURRENT OF c_lock;
REF CURSOR 動態游標
| 類型 | 宣告語法 | 特點 |
| 強型別 | TYPE ref_cur IS REF CURSOR RETURN table%ROWTYPE; | 編譯期綁定回傳結構 |
| 弱型別 | TYPE ref_cur IS REF CURSOR; | 執行期動態決定結構,靈活度高 |
弱型別 REF CURSOR 範例
DECLARE
TYPE ref_cur IS REF CURSOR;
v_cur ref_cur;
BEGIN
OPEN v_cur FOR SELECT * FROM admin WHERE dept_id = 10;
-- FETCH 迴圈處理
CLOSE v_cur;
END;
強型別 REF CURSOR 範例
DECLARE
TYPE ref_cur IS REF CURSOR RETURN admin%ROWTYPE;
v_cur ref_cur;
BEGIN
OPEN v_cur FOR SELECT * FROM admin;
CLOSE v_cur;
END;
最佳實踐提醒
- 盡量使用
FOR rec IN cursor LOOP ... END LOOP; 隱性游標,自動處理 OPEN/FETCH/CLOSE,程式碼更簡潔安全。
- 游標變數(REF CURSOR)適合作為程序間傳遞結果集,或動態 SQL 場景。
FOR UPDATE 鎖定行級鎖,務必在最短邏輯內 COMMIT/ROLLBACK 釋放,避免阻塞併發。