遊標是一個私有的SQL工作區域,Oracle數據庫中有兩種遊標,分別是隱式遊標和顯式遊標, 隱式遊標不易被用戶和程序員察覺和意識到,實際上Oracle服務器使用隱式遊標來解析和執行我們提交的SQL 語句; 而顯式遊標是程序員在程序中顯式聲明的;通常我們說的遊標均指顯式遊標。
隱式遊標的幾個有用屬性:
SQL%ROWCOUNT 受最近的SQL語句影響的行數
SQL%FOUND 最近的SQL語句是否影響了一行以上的 數據
SQL%NOTFOUND 最近的SQL語句是否未影響任何數據
SQL%ISOPEN 對於隱式遊標而言永遠爲FALSE
例如:
VARIABLE rows_deleted VARCHAR2(30)
DECLARE
v_employee_id employees.employee_id%TYPE := 176;
BEGIN
DELETE FROM employees WHERE
employee_id = v_employee_id;
rows_deleted := (SQL%ROWCOUNT ||' row deleted.');
END;
顯式遊標:
1、一行一行的處理返回的數據。
2、保持當前處理行的一個跟蹤,像一個指針一樣指示當前的處理的記錄。
3、允許程序員在PLSQL塊中人爲的控制遊標的開啓、關閉、上下移動;
此圖爲顯式遊標標準的語句
如果你覺得像前面那個例子那樣對一個遊標的遍歷很麻煩的話,可以考慮使用For循環,For循環省去了遊標的 聲明、打開、提取、測試、關閉等語句,對程序員來說很方便,語法如下:——————兩種方法
DECLARE
CURSOR emp_cursor IS
SELECT employee_id
,last_name
,departments.department_name
FROM employees
,departments
WHERE employees.department_id = departments.department_id
AND employees.department_id = 90
FOR UPDATE OF salary NOWAIT ;
BEGIN
FOR emp_data IN emp_cursor LOOP
UPDATE employees e
SET e.salary = 29999
--where e.employee_id = emp_data.employee_id
WHERE CURRENT OF emp_cursor;
END LOOP;
END;
或者:
BEGIN
FOR emp_record IN (SELECT last_name, department_id
FROM employees) LOOP
-- implicit open and implicit fetch occur
IF emp_record.department_id = 80 THEN
... END LOOP; -- implicit close occurs
END;
遊標可以帶參數:
例如:
DECLARE
CURSOR emp_cursor (p_deptno NUMBER, p_job VARCHAR2) IS
SELECT employee_id, last_name
FROM employees
WHERE department_id = p_deptno
AND job_id = p_job;
BEGIN
OPEN emp_cursor (80, 'SA_REP');
. . .
CLOSE emp_cursor;
OPEN emp_cursor (60, 'IT_PROG');
. . .
END;
FOR UPDATE NOWAIT語句:有的時候我們打開一個遊標是爲了更新或者刪除一些記錄,這種情況下我們希望 在打開遊標的時候即鎖定相關記錄,應該使用for update nowait語句,倘若鎖定失敗我們就停止不再繼續,以免 出現長時間等待資源的死鎖情況。
DECLARE
CURSOR emp_cursor IS
SELECT employee_id, last_name, department_name
FROM employees,departments
WHERE employees.department_id =
departments.department_id
AND employees.department_id = 80
FOR UPDATE OF salary NOWAIT;
WHERE CURRENT OF cursor :
我們經常要逐條處理遊標中的每一條記錄,在循環體內做Update 或者 Delete 時需要有Where指向遊標的當前記錄, 有沒有簡單一點的的Where條件寫法呢?
DECLARE
CURSOR sal_cursor IS
SELECT e.department_id, employee_id, last_name, salary
FROM employees e, departments d
WHERE d.department_id = e.department_id
and d.department_id = 60
FOR UPDATE OF salary NOWAIT;
BEGIN
FOR emp_record IN sal_cursor
LOOP
IF emp_record.salary < 5000 THEN
UPDATE employees
SET salary = emp_record.salary * 1.10
WHERE CURRENT OF sal_cursor;
END IF;
END LOOP;
END;