顯式游標
處理顯式游標需要四個 PL/SQL步驟:
定義游標:就是定義一個游標名,以及與其相對應的SELECT 語句
CURSOR cursor_name IS select_statement;
打開游標:OPEN cursor_name
提取游標:就是檢索結果集合中的數據行,放入指定的輸出變量中
FETCH cursor_name INTO {variable_list | record_variable };
關閉游標:當提取和處理完游標結果集合數據后,應及時關閉游標,以釋放該游標所占用的系統資源,
並使該游標的工作區變成無效,不能再使用FETCH 語句取其中數據。
關閉后的游標可以使用OPEN 語句重新打開
CLOSE cursor_name;
例:
1 DECLARE 2 3 v_ename emp.ename%TYPE; 4 5 v_sal emp.sal%TYPE; 6 7 CURSOR c_cursor IS SELECT ename, sal FROM emp WHERE rownum<11; 8 9 BEGIN 10 11 OPEN c_cursor; 12 13 FETCH c_cursor INTO v_ename, v_sal; 14 15 WHILE c_cursor %FOUND LOOP 16 17 DBMS_OUTPUT.PUT_LINE(v_ename||'---'||to_char(v_sal) ); 18 19 FETCH c_cursor INTO v_ename, v_sal; 20 21 END LOOP; 22 23 CLOSE c_cursor; 24 25 END;
參數化游標
例:
DECLARE v_ename emp.ename%TYPE; v_sal emp.sal%TYPE; CURSOR c_cursor(P_sal emp.sal%type) IS SELECT ename, sal FROM emp WHERE sal >= P_sal; BEGIN OPEN c_cursor(1000); FETCH c_cursor INTO v_ename, v_sal; WHILE c_cursor %FOUND LOOP DBMS_OUTPUT.PUT_LINE(v_ename||'---'||to_char(v_sal) ); FETCH c_cursor INTO v_ename, v_sal; END LOOP; CLOSE c_cursor; END;
游標屬性
%FOUND :布爾型屬性,當最近一次讀記錄時成功返回,則值為TRUE;
%NOTFOUND :布爾型屬性,與%FOUND相反
%ISOPEN: 布爾型屬性,當游標已打開時返回 TRUE;
%ROWCOUNT:數字型屬性,返回已從游標中讀取的記錄數。
處理隱式游標
例:
1 DECLARE 2 3 V_deptno emp.deptno%TYPE :=&p_deptno; 4 5 BEGIN 6 7 DELETE FROM emp WHERE deptno=v_deptno; 8 9 IF SQL%NOTFOUND THEN 10 11 DELETE FROM dept WHERE deptno= 20; 12 13 END IF; 14 15 END;
游標檢索循環
例:
1 DECLARE 2 3 v_empno emp.empno%TYPE; 4 5 v_sal emp.sal%TYPE; 6 7 CURSOR c_cursor IS SELECT empno, sal FROM emp; 8 9 BEGIN 10 11 OPEN c_cursor; 12 13 LOOP 14 15 FETCH c_cursor INTO v_empno, v_sal; 16 17 EXIT WHEN c_cursor %NOTFOUND; 18 19 IF v_sal<=1200 THEN 20 21 UPDATE emp SET sal=sal+50 WHERE empno=v_empno; 22 23 DBMS_OUTPUT.PUT_LINE('編碼為'||v_empno||'工資已更新!'); 24 25 END IF; 26 27 DBMS_OUTPUT.PUT_LINE('記錄數:'|| c_cursor %ROWCOUNT); 28 29 END LOOP; 30 31 CLOSE c_cursor; 32 33 END;
游標的FOR循環
FOR index_variable IN cursor_name[value[, value]…] LOOP
-- 游標數據處理代碼
END LOOP;
例:
1 DECLARE 2 3 CURSOR c_sal IS SELECT empno, ename, sal FROM emp ; 4 5 BEGIN 6 7 --隱含打開游標 8 9 FOR v_sal IN c_sal LOOP 10 11 --隱含執行一個FETCH語句 12 13 DBMS_OUTPUT.PUT_LINE( to_char(v_sal.empno)||’---‘||v_sal.ename||’---‘||to_char(v_sal.sal)) ; 14 15 --隱含監測c_sal%NOTFOUND 16 17 END LOOP; 18 19 --隱含關閉游標 20 21 END;
SELECT FOR UPDATE 游標
游標修改和刪除操作是指在游標定位下,修改或刪除表中指定的數據行。這時,要求游標查詢語句中必須使用FOR UPDATE選項
SELECT . . . FROM … FOR UPDATE [OF column[, column]…] [NOWAIT]
例:DECLARE
V_deptno emp.deptno%TYPE :=&p_deptno;
CURSOR emp_cursor IS SELECT empno, sal
FROM emp WHERE deptno=v_deptno FOR UPDATE NOWAIT;
BEGIN
FOR emp_record IN emp_cursor LOOP
IF emp_record.sal < 1500 THEN
UPDATE emp SET sal=1500 WHERE CURRENT OF emp_cursor;
END IF;
END LOOP;
--COMMIT;
END;
游標變量
與游標一樣,游標變量也是一個指向多行查詢結果集合中當前數據行的指針。但與游標不同的是,游標變量是動態的,而游標是靜態的。游標只能與指定的查詢相連,即固定指向一個查詢的內存處理區域,而游標變量則可與不同的查詢語句相連,它可以指向不同查詢語句的內存處理區域(但不能同時指向多個內存處理區域,在某一時刻只能與一個查詢語句相連),只要這些查詢語句的返回類型兼容即可。
游標變量為一個指針,它屬於參照類型,所以在聲明游標變量類型之前必須先定義游標變量類型。
TYPE ref_type_name IS REF CURSOR [ RETURN return_type] (強[弱]游標變量)
例:聲明兩個強類型定義游標變量和一個弱類型游標變量
1 DECLARE 2 3 TYPE deptrecord IS RECORD( 4 5 Deptno dept.deptno%TYPE, 6 7 Dname dept.deptno%TYPE, 8 9 Loc dept.loc%TYPE ); 10 11 TYPE deptcurtype IS REF CURSOR RETURN dept%ROWTYPE; 12 13 TYPE deptcurtyp1 IS REF CURSOR RETURN deptrecord; 14 15 TYPE curtype IS REF CURSOR; 16 17 Dept_c1 deptcurtype; 18 19 Dept_c2 deptcurtyp1; 20 21 Cv curtype;
打開游標變量 :打開游標變量時使用的是OPEN…FOR 語句
提取游標變量數據 :
關閉游標變量 :
例:強類型參照游標變量類型
1 DECLARE 2 3 TYPE emp_job_rec IS RECORD( 4 5 Employee_id emp.empno%TYPE, 6 7 Employee_name emp.ename%TYPE, 8 9 Job_title emp.job%TYPE); 10 11 TYPE emp_job_refcur_type IS REF CURSOR RETURN emp_job_rec; 12 13 Emp_refcur emp_job_refcur_type ; 14 15 Emp_job emp_job_rec; 16 17 BEGIN 18 19 OPEN emp_refcur FOR 20 21 SELECT empno, ename, job FROM emp ORDER BY deptno; 22 23 FETCH emp_refcur INTO emp_job; 24 25 WHILE emp_refcur%FOUND LOOP 26 27 DBMS_OUTPUT.PUT_LINE(emp_job.employee_id||’: ‘||emp_job.employee_name||‘ is a ’||emp_job.job_title); 28 29 FETCH emp_refcur INTO emp_job; 30 31 END LOOP; 32 33 END;
例:弱類型參照游標變量類型
1 DECLARE 2 3 Type refcur_t IS REF CURSOR; 4 5 Refcur refcur_t; 6 7 TYPE sample_rec_type IS RECORD ( 8 9 Id number, 10 11 Description VARCHAR2 (30) ); 12 13 sample sample_rec_type; 14 15 selection varchar2(1) := UPPER (SUBSTR (‘&tab’, 1, 1)); 16 17 BEGIN 18 19 IF selection=’D’ THEN 20 21 OPEN refcur FOR SELECT deptno, dname FROM dept; 22 23 DBMS_OUTPUT.PUT_LINE(‘Department data’); 24 25 ELSIF selection=’E’ THEN 26 27 OPEN refcur FOR SELECT empno, ename||’ is a ‘||job FROM emp; 28 29 DBMS_OUTPUT.PUT_LINE(‘Employee data’); 30 31 ELSE 32 33 DBMS_OUTPUT.PUT_LINE(‘Please enter ‘‘D’’ or ‘‘E’’ ’); 34 35 RETURN; 36 37 END IF; 38 39 DBMS_OUTPUT.PUT_LINE(‘----------------------‘); 40 41 FETCH refcur INTO sample; 42 43 WHILE refcur%FOUND LOOP 44 45 DBMS_OUTPUT.PUT_LINE(sample.id||’: ‘||sample.description); 46 47 FETCH refcur INTO sample; 48 49 END LOOP; 50 51 CLOSE refcur; 52 53 END;