在PL/SQL塊中執行CRUD語句時,ORACLE會在內存中爲其分配上下文區(Context Area),即緩衝區。遊標是指向該區的一個指針,或是命名一個工做區(Work Area),或是一種結構化數據類型。
1.顯式遊標。即用戶自定義遊標,用於處理select語句返回的多行數據oop
declare cursor cur_emp(i_job varchar2) is select employee_id, job_id from employees where job_id = i_job; v_emp cur_emp%rowtype; begin open cur_emp('ST_CLERK'); loop fetch cur_emp into v_emp; exit when cur_emp%notfound; dbms_output.put_line(v_emp.employee_id || v_emp.job_id); end loop; close cur_emp; end;
cursor_name%ISOPEN 遊標是否打開
cursor_name%FOUND 最近的FETCH是否提取到數據
cursor_name%NOTFOUND 最近的FETCH是否沒有提取到數據
cursor_name%ROWCOUNT 返回到目前爲止,已經從遊標緩衝區中提取到數據的行數fetch
2.隱式遊標。系統自動定義的遊標,記錄集只有單行數據,用於處理select into 和DML語句ui
DECLARE v_rows NUMBER; BEGIN UPDATE employees SET salary = 2333 WHERE department_id = 90 AND job_id = 'AD_VP'; dbms_output.put_line('更新了' || SQL%rowcount || '個僱員的工資'); IF SQL%found THEN dbms_output.put_line('成功!'); END IF; END;
相似於顯示遊標,隱式遊標一樣具備四種屬性,只不過隱式遊標以SQL%開頭,而顯示遊標以Cursor_name%開頭。經過SQL%老是隻能訪問前一個DML操做或單行SELECT操做的遊標屬性,用於判斷DML執行的狀態和結果,進而控制程序的流程指針
SQL%ISOPEN 遊標是否打開。當執行select into ,insert update,delete時,Oracle會隱含地打開遊標,且在該語句執行完畢或隱含地關閉遊標,由於是隱式遊標,故SQL%ISOPEN老是false
SQL%FOUND 判斷SQL語句是否成功執行。當有做用行時則成功執行爲true,不然爲false
SQL%NOTFOUND 判斷SQL語句是否成功執行。當有做用行時否其值爲false,不然其值爲true。
SQL%ROWCOUNT 在執行任何DML語句以前,SQL%ROWCOUNT的值都是NULL,對於SELECT INTO語句,若是執行成功,SQL%ROWCOUNT的值爲,若是沒有成功,SQL%ROWCOUNT的值爲,同時產生一個異常NO_DATA_FOUND。
更新或刪除當前遊標數據
遊標查詢語句中必須使用FOR UPDATE選項,以便在打開遊標時鎖定遊標結果集合在表中對應數據行的全部列和部分列。 若是另外一個會話已對活動集中的行加了鎖,那麼SELECT FOR UPDATE操做一直等待到其它的會話釋放這些鎖後才繼續本身的操做;對於這種狀況,當加上NOWAIT子句時,若是這些行真的被另外一個會話鎖定,則OPEN當即返回並給出: ORA-0054 :resource busy and acquire with nowait specified.code
DECLARE V_deptno employees.department_id%TYPE; CURSOR emp_cursor IS SELECT employees.employee_id, employees.salary FROM employees WHERE employees.department_id = v_deptno FOR UPDATE NOWAIT; --一、for update BEGIN FOR emp_record IN emp_cursor LOOP IF emp_record.salary < 1500 THEN UPDATE employees SET salary = 1500 WHERE CURRENT OF emp_cursor; --二、WHERE CURRENT OF cursor_name子句 END IF; END LOOP; END;
3.動態遊標REF CURSOR內存
DECLARE --定義一個遊標數據類型 TYPE cur_emp IS REF CURSOR; --聲明一個遊標變量 c1 cur_emp; --聲明兩個記錄變量 v_emp employees%rowtype; v_rgn regions%rowtype; BEGIN OPEN c1 FOR SELECT * FROM employees WHERE department_id = 20; LOOP FETCH c1 INTO v_emp; EXIT WHEN c1%notfound; dbms_output.put_line(v_emp.first_name || '的僱傭日期是' || v_emp.hire_date); END LOOP; --將同一個遊標變量對應到另外一個SELECT語句 OPEN c1 FOR SELECT * FROM regions WHERE region_id IN (1, 2); LOOP FETCH c1 INTO v_rgn; EXIT WHEN c1%notfound; dbms_output.put_line(v_rgn.region_id || '表示' || v_rgn.region_name); END LOOP; CLOSE c1; END;
4.使用包
包頭ci
CREATE OR REPLACE PACKAGE TESTPACKAGE AS TYPE empcursor IS REF CURSOR; PROCEDURE queryEmpList(dno in number,emplist out empcursor); END TESTPACKAGE;
包體it
CREATE OR REPLACE PACKAGE BODY TESTPACKAGE AS PROCEDURE queryEmpList(dno in number,emplist out empcursor) AS BEGIN OPEN emplist FOR SELECT * FROM emp WHERE deptno=dno; END queryEmpList; END TESTPACKAGE;
注意:訪問時須要帶包名io