for update 与where current of的问题

在刚学oracle时一直不明白for update 的做用,今天考试又遇到郁闷半天,因此加以整理。java

一:sql

1>首先for update是对表的行进行锁定。锁定就比如咱们学java Thread那一章时,为某个线程的run()枷锁,当实例化出来多个线程时,它必须一个线程所有执行完后,释放锁其余线程才有机会运行。本文for update功能上同样,就是为一个select语句枷锁,这样在对这个表进行update ,delete时就会处于等待状态,等待selec执行commit或rollback(至关于线程释放锁)后,才能够对表进行更改或删除。数据库

怎样看效果呢?1:首先在“运行”-->cmd-->链接数据库 执行select * from emp for updateoracle

    2 :而后在打开另外一个窗口(就至关于建立了两个用户):“运行”-->cmd-->链接数据库  执行update emp set sal=100;你会发现它不执行了。spa

2>那马for update与for update of 有神马区别呢?线程

1.select * from Table1 for update 锁定表的全部行,只能读不能写 code

  2  select * from Table1 where id = 1 for update 只锁定id=1的行ip

  3  select * from Table1 a join Table2 b on a.id=b.id for update 锁定两个表的全部记录资源

  4 select * from Table1 a join Table2 b on a.id=b.id where a.id = 10 for update 锁定两个表的中知足条件的行cmd

  5. select * from Table1 a join Table2 b on a.id=b.id where a.id = 10 for update of a.id 只锁定Table1中知足条件的行

  for update 是把全部的表都锁点 for update of 根据of 后表的条件锁定相对应的表

3>关于oracle:select...for update of columns

按照1>步骤执行1:select * from emp for update of sal在另外一个窗口中执:2:update emp set job='clerk' where empno=10;按照2>的的思惟咱们可能认:“1”只锁定了emp表的sal列,其实否则当运行“2”时,咱们发现它任然不执行,因此for update of columns 是锁定的与sal相关的行。那么for update 与for update of 有神吗区别呢?区别在于多表链接时;

例如:

按照1>分别执行 select ename,dname from emp,dept where emp.deptno=dept.deptno for update;

另外一窗口执行:update dept set dname='haha'where deptno=10;咱们发现dept表不能更改

当咱们在 select ename,dname from emp,dept where emp.deptno=dept.deptno for update of sal;时

update dept set dname='haha'where deptno=10;能够在执行了。

由此咱们能够综结出:for update of columns 用在多表链接锁定时,能够指定要锁定的是哪几张表,而若是表中的列没有在for update of 后面出现的话,就意味着这张表其实并无被锁定,其余用户是能够对这些表的数据进行update操做的。这种状况常常会出如今用户对带有链接查询的视图进行操做场景下。用户只锁定相关表的数据,其余用户仍然能够对视图中其余原始表的数据来进行操做。

4>关于nowait与wait

SELECT ... FOR UPDATE [OF column_list][WAIT n|NOWAIT][SKIP LOCKED]; 
1:其中: 

  OF 子句用于指定即将更新的列,即锁定行上的特定列。 

NOWAIT不进行等待,若是这条语句的锁没被释放,则会直接报出:系统资源正忙
  WAIT 子句指定等待其余用户释放锁的秒数,防止无限期的等待。 
  “使用FOR UPDATE WAIT”子句的优势以下: 
  1防止无限期地等待被锁定的行; 
  2容许应用程序中对锁的等待时间进行更多的控制。 
  3对于交互式应用程序很是有用,由于这些用户不能等待不肯定 
  4 若使用了skip locked,则能够越过锁定的行,不会报告由wait n 引起的‘资源忙’异常报告 :

2:如今执行以下操做: 

在plsql develope中打开两个sql窗口, 在1窗口中运行sql 
select * from t where a='1' for update; 
在2窗口中运行sql1 
1. select * from t where a='1'; 这一点问题也没有,由于行级锁不会影响纯粹的select语句 
再运行sql2 
2. select * from t where a='1' for update; 则这一句sql在执行时,永远处于等待状态除非窗口1中sql 被提交或回滚。 
如何才能让sql2不等待或等待指定的时间呢? 咱们再运行sql3 
3. select * from t where a='1' for update nowait; 则在执行此sql时,直接报资源忙的异常。 
若执行 select * from t where a='1' for update wait 6; 则在等待6秒后,报 资源忙的异常。 若是咱们执行 sql4 
4. select * from t where a='1' for update nowait skip Locked; 则执行sql时,即不等待,也不报资源 忙异常。 
如今咱们看看执行以下操做将会发生什么呢? 
在窗口1中执行: 
select * from t where rownum<=3 nowait skip Locked; 
在窗口2中执行: 
select * from t where rownum<=6 nowait skip Locked; 
select for update 也就如此了吧,insert、update、delete操做默认加行级锁,其原理和操做与select for update并没有两样。 
select for update of,这个of子句在牵连到多个表时,具备较大做用,如不使用of指定锁定的表的列,则全部表的相关行均被锁定,若在of中指定了需修改的列,则只有与这些列相关的表的行才会被锁定.

二:

1:

若是你想删除或者更新被Select For Update引用的记录,你可使用Where Current Of语句

 

  1.  
    DECLARE
  2.  
    CURSOR CUR_NAME IS
  3.  
    SELECT * FROM EMP WHERE deptno=10 FOR UPDATE OF sal;
  4.  
    BEGIN
  5.  
    FOR REC IN CUR_NAME LOOP
  6.  
    UPDATE EMP SET sal =100 ;
  7.  
    END LOOP;
  8.  
    END;

上述pl/sql执行过以后咱们发现emp表中全部的sal列数据都被更改,此时咱们只想更改跟游标对应的行,因此咱们又到where current of执行游标遍历时的当前行就好像for(int i=0;i++;i<10){}where current of与“i”的功能类似。因此当咱们想执行游标影响的行时,上咱们能够把上面pl/sql快改成:

 

    1.  
      DECLARE
    2.  
      CURSOR CUR_NAME IS
    3.  
      SELECT JOB FROM EMP WHERE deptno=10 FOR UPDATE OF sal;
    4.  
      BEGIN
    5.  
      FOR REC IN CUR_NAME LOOP
    6.  
      UPDATE EMP SET sal =100 WHERE CURRENT OF CUR_NAME;
    7.  
      END LOOP;
    8.  
      END;
相关文章
相关标签/搜索