游标修改和删除操作是指在游标定位下,修改或删除表中指定的数据行。要求游标查询语句中必须使用 FOR UPDATE 选项,以便在打开游标时锁定游标结果集合在表中对应数据行的所有列和部分列。
FOR UPDATE 子句会锁定游标结果集选择的行,这样防止数据不被其他会话改动。 其他会话对这些行数据无法加锁,直到事务处理提交或回退为止。
语法如下:
SELECT . . . FROM … FOR UPDATE [OF column[, column]…] [NOWAIT]
如果另一个会话已对活动集中的行加了锁,那么 SELECT FOR UPDATE 操作一直等待到其它的会话释放这些锁后才继续自己的操作,对于这种情况,当加上 NOWAIT 子句时,如果这些行被另一个会话锁定,则 OPEN 立即退出并报错:ORA-30006: resource busy; acquire with WAIT timeout expired
。
如果使用 FOR UPDATE 声明游标,则可在 DELETE 和 UPDATE 语句中使用 WHERE CURRENT OF cursor_name
子句修改或删除游标结果集合当前行对应的数据库表中的数据行。
如下例所示:
obclient> SELECT first_name, salary FROM employees WHERE department_id=110;
+------------+--------+
| FIRST_NAME | SALARY |
+------------+--------+
| Shelley | 12008 |
| William | 8300 |
+------------+--------+
2 rows in set (0.00 sec)
obclient> DECLARE
-> V_deptno employees.department_id%TYPE :=110;
-> CURSOR c_emp IS SELECT first_name, salary
-> FROM employees WHERE department_id=V_deptno FOR UPDATE NOWAIT;
-> BEGIN
-> FOR emp_record IN c_emp LOOP
-> IF emp_record.salary < 9000 THEN
-> UPDATE employees SET salary=9000 WHERE CURRENT OF c_emp;
-> END IF;
-> END LOOP;
-> END;
-> /
Query OK, 0 rows affected (0.03 sec)
obclient> SELECT first_name, salary FROM employees WHERE department_id=110;
+------------+--------+
| FIRST_NAME | SALARY |
+------------+--------+
| Shelley | 12008 |
| William | 9000 |
+------------+--------+
2 rows in set (0.00 sec)