| 類型 | 定義位置 | 適用場景 | 管理方式 |
|---|---|---|---|
| 顯式游標 | PL/SQL 宣告區 | SELECT 查詢,需逐行處理 | 手動 OPEN/FETCH/CLOSE |
| 隱式游標 | SQL 引擎自動建立 | DML(INSERT/UPDATE/DELETE)、單行 SELECT | 自動開啟/關閉,透過 SQL% 屬性檢測 |
CURSOR c_name IS SELECT ...OPEN c_name;FETCH c_name INTO variables | record;CLOSE c_name;CREATE TABLE student (
stuname VARCHAR2(10),
stuno VARCHAR2(4),
age NUMBER,
gender VARCHAR2(2)
);
CREATE OR REPLACE PROCEDURE proc_stu1 AS
BEGIN
DECLARE
CURSOR cur_stu IS SELECT stuno, stuname FROM student ORDER BY stuno;
v_stuno VARCHAR2(4);
v_stuname VARCHAR2(20);
BEGIN
OPEN cur_stu;
FETCH cur_stu INTO v_stuno, v_stuname;
WHILE cur_stu%FOUND LOOP
DBMS_OUTPUT.PUT_LINE(v_stuno || '->' || v_stuname);
FETCH cur_stu INTO v_stuno, v_stuname;
END LOOP;
CLOSE cur_stu;
END;
END;
CREATE OR REPLACE PROCEDURE proc_stu2 AS
BEGIN
DECLARE
CURSOR cur_stu IS SELECT stuno, stuname FROM student ORDER BY stuno;
v_stuno VARCHAR2(4);
v_stuname VARCHAR2(20);
BEGIN
OPEN cur_stu;
FETCH cur_stu INTO v_stuno, v_stuname;
LOOP
IF cur_stu%FOUND THEN
DBMS_OUTPUT.PUT_LINE(v_stuno || '->' || v_stuname);
FETCH cur_stu INTO v_stuno, v_stuname;
ELSE
EXIT;
END IF;
END LOOP;
CLOSE cur_stu;
END;
END;
CREATE OR REPLACE PROCEDURE proc_stu3 AS
BEGIN
DECLARE
CURSOR cur_stu IS SELECT stuno, stuname FROM student ORDER BY stuno;
BEGIN
FOR stu_rec IN cur_stu LOOP
DBMS_OUTPUT.PUT_LINE(stu_rec.stuno || '->' || stu_rec.stuname);
-- 隱式檢測 %NOTFOUND,自動 OPEN/CLOSE
END LOOP;
END;
END;
優勢:程式碼最簡潔、不易忘記關閉、記錄變數自動匹配欄位。
CREATE OR REPLACE PROCEDURE proc_stu4 AS
BEGIN
DECLARE
CURSOR cur_stu IS SELECT stuno, stuname FROM student ORDER BY stuno;
v_stuno VARCHAR2(4);
v_stuname VARCHAR2(20);
BEGIN
OPEN cur_stu;
LOOP
FETCH cur_stu INTO v_stuno, v_stuname;
EXIT WHEN cur_stu%NOTFOUND; -- 提取後立即判斷,避免多餘判斷
DBMS_OUTPUT.PUT_LINE(v_stuno || '->' || v_stuname);
END LOOP;
CLOSE cur_stu;
END;
END;
關鍵差異:FETCH 放在迴圈開頭,EXIT WHEN 緊隨其後,邏輯清晰且僅一次條件判斷。
CREATE OR REPLACE PROCEDURE proc_upsert AS
BEGIN
UPDATE student SET stuname = '張燕廣' WHERE stuno = '1104';
IF SQL%NOTFOUND THEN -- 隱式游標屬性檢測 UPDATE 影響行數
INSERT INTO student (stuno, stuname, age, gender)
VALUES ('1104', '張燕廣', 18, '男');
END IF;
END;
隱式游標屬性(SQL%FOUND、SQL%NOTFOUND、SQL%ROWCOUNT、SQL%ISOPEN)僅在最近一條 DML 執行後有效。
CURSOR c(p_deptno NUMBER) IS SELECT ... WHERE deptno = p_deptno; 促進重用與軟解析。SYS_REFCURSOR 實現動態查詢與跨程序傳遞。