(转)oracle.for update,更新游标,cursor

http://blog.csdn.net/yanleigis/article/details/2950208

oracle dml select for update syntax examples

在多数情况下,提取循环中所完成的处理都会修改由游标检查出的行,PL/SQL提供了进行这样处理的一种语法。
这种语法包括两部分——在游标声明部分的FOR UPDATE子句和在UPDATE或DELETE语句中的WHERE CURRENT OF 子句。 
通常,SELECT操作将不会对正处理的行执行任何锁定设置,这使得连接到该数据库的其他会话可以改变正在选择的数据。 
但是,结果集仍然是一致性的。当确定了活动集以后,在执行OPEN的时刻,ORACLE会截取下该表的一个快照。在此时刻以前所提交的任何更改操作都会在活动集中反映出来。在此时刻以后所进行的任何更改操作,即使已经提交了它们,都不会被反映出来,除非将该游标重新打开。但是使用FOR UPDATE子句,在OPEN返回以前的活动集的相应行上会加上互斥锁,这些锁会避免其他的会话对活动集中的行进行更改。直到整个事务被提交为止。 

示例: 
DECLARE 
CURSOR C_CUR IS SELECT * FROM STUDENDS FOR UPDATE OF XM; 
BEGIN 
OPEN C_CUR; 
WHILE C_CUR%FOUND LOOP 

UPDATE STUDENDS SET XM='AA'||XM WHERE CURRENT OF C_CUR; 

END LOOP; 
CLOSE C_CUR; 
COMMIT; 
END; 


需要注意的是:1、 UPDATE语句仅更新在游标声明的FOR UPDATE子句处列出的列(这句话有错误,经试验和查询证明,UPDATE语句可以更新游标声明的 FOR UPDATE 中涉及到的表的所有列)。如果没有列出任何列,那么所有的列都可以更新。 
2、示例中的COMMIT是在提取循环完成以后才完成的,因为COMMIT将释放由该会话持有的所有锁。因为FOR UPDATE子句获得了锁,所以COMMIT将释放这些锁。当锁释放了,该游标就无效了。所以后继的提取操作都将返回ORACLE错误。
在定义又表示必须要带有for update子句,用于在游标结果集数据上加行共享锁,以防止其他用户在相应行上执行dml操作;当select语句引用到多张表时,使用of子句可以确定哪些表要加锁,如果没有of子句,则会在select语句所引用的全部表上加锁;nowait子句用于指定不等待锁。在提取了游标数据之后,为了更新或删除当前游标行数据,必须在update或delete语句中引用where current of 子句。 
--1、使用游标更新数据 
Java代码   收藏代码
  1. declare  
  2. cursor emp_cursor is  
  3. --加行共享锁  
  4. select t.name,t.english_name from communitytype t for update;  
  5. --定义变量  
  6. v_name communitytype.name%type;  
  7. v_enname communitytype.english_name%type;  
  8. begin  
  9. --打开游标  
  10. open emp_cursor;  
  11. loop  
  12. fetch emp_cursor into v_name,v_enname;  
  13. exit when emp_cursor%notfound;  
  14. if v_name = '电子图书' then  
  15. update communitytype c  
  16. set c.english_name = 'ebook'  
  17. where current of emp_cursor;  
  18. end if;  
  19. end loop;  
  20. close emp_cursor;  
  21. commit;  
  22. end;  

--2、使用游标删除数据,同上只需要将更新语句换成删除语句 
--3、使用of子句在特定表上加行共享锁 
Java代码   收藏代码
  1. declare  
  2. cursor emp_cursor is  
  3. --加行共享锁  
  4. select t.name,t.english_name from communitytype t for update of t.name;  
  5. --定义基于游标的记录变量  
  6. emp_record emp_cursor%rowtype;  
  7. begin  
  8. --打开游标  
  9. open emp_cursor;  
  10. loop  
  11. fetch emp_cursor into emp_record;  
  12. exit when emp_cursor%notfound;  
  13. if emp_record.name = '电子图书' then  
  14. update communitytype c  
  15. set c.english_name = 'ebook'  
  16. where current of emp_cursor;  
  17. end if;  
  18. end loop;  
  19. close emp_cursor;  
  20. commit;  
  21. end;  

--4、默认情况下当前会话要一直等待对方释放锁,使用nowait子句可以避免等待锁 
Java代码   收藏代码
  1. declare  
  2. cursor emp_cursor is  
  3. --加行共享锁  
  4. select t.name,t.english_name from communitytype t for update nowait;  
  5. --定义基于游标的记录变量  
  6. emp_record emp_cursor%rowtype;  
  7. begin  
  8. --打开游标  
  9. open emp_cursor;  
  10. loop  
  11. fetch emp_cursor into emp_record;  
  12. exit when emp_cursor%notfound;  
  13. if emp_record.name = '电子图书' then  
  14. update communitytype c  
  15. set c.english_name = 'ebook'  
  16. where current of emp_cursor;  
  17. end if;  
  18. end loop;  
  19. close emp_cursor;  
  20. commit;  
  21. end;  

猜你喜欢

转载自ruotongsong.iteye.com/blog/1859282