FOR UPDATE OF和FOR UPDATE之间的区别

Rav*_*avi 8 oracle locking sql-update

当我使用FOR UPDATE OF SAL或简单地写时,有什么不同FOR UPDATE.

根据奥莱利的说法

FOR UPDATE子句的OF列表不限制您仅更改列出的列.锁仍然放在所有行上; OF列表只是为您提供了一种更清楚地记录您想要更改的内容的方法.如果您只是在查询中声明FOR UPDATE并且在OF关键字之后不包含一个或多个列,那么数据库将锁定FROM子句中列出的所有表中的所有标识的行.

这意味着,当我指定列名时FOR UPDATE OF SAL,其他用户只能使用SAL列进行更改.但实际情况并非如此.我还在锁定其他会话.任何人都可以解释这种差异

UPDATE

 ----- SESSION 1

declare
 emp_info emp.ename%type;
 cursor emp_cur is select ename from emp join dept using(deptno) where deptno=&no for update of sal;
 begin
 open emp_cur;
 loop
 fetch emp_cur into emp_info;
 exit when emp_cur%notfound;
 dbms_output.put_line(emp_info);
 end loop;
 close emp_cur;
 end;

  ----- SESSION 2

  update emp set comm=5 where deptno=10;
  ---- hanged/waiting in session 2
Run Code Online (Sandbox Code Playgroud)

Ale*_*ole 17

Oracle文档:

使用OF ...column子句仅锁定连接中特定表或视图的选择行.OF子句中的列仅指示锁定哪些表或视图行.您指定的特定列不重要.但是,您必须指定实际的列名称,而不是列别名.如果省略此子句,则数据库将锁定查询中所有表中的选定行.

如果您的查询引用单个表,则FOR UPDATE和之间没有区别FOR UPDATE OF ...,但后者可能仍然可用作自我文档以指示您要更新的列.它不限制你可以更新的内容.如果你有:

CURSOR cur IS SELECT * FROM emp FOR UPDATE OF sal;
Run Code Online (Sandbox Code Playgroud)

然后你仍然可以做:

UPDATE emp SET comm = comm * 1.1 WHERE CURRENT OF cur;
Run Code Online (Sandbox Code Playgroud)

但是,如果有多个表,则FOR UPDATE OF ...只会锁定包含您在OF子句中指定的列的表中的行.

与我认为你在问题中所说的相反.指定FOR UPDATE OF sal不仅会锁定sal列; 您永远不能锁定单个列,最小锁定在行级别.(阅读更多关于锁的信息).它锁定包含SAL列的表中的所有行,这些行由查询选择.


在更新你的问题,你的光标查询加入empdept,但OF条款只sal,在一列emp的表.emp打开游标时,表中的行将被锁定,并且在您commitrollback该会话之前不会释放这些锁.在游标循环中,您可以:

UPDATE emp SET ... WHERE CURRENT OF emp_cur;
Run Code Online (Sandbox Code Playgroud)

...更新emp表中与循环迭代相关的行.你不能做的:

UPDATE dept SET ... WHERE CURRENT OF emp_cur;
Run Code Online (Sandbox Code Playgroud)

...因为dept表中的行没有被锁定,因为没有列OF.这也意味着在第二个会话中,dept行可以自由更新,因为它们不会被第一个会话锁定.