2013-04-18 14 views
6

Điều gì tạo nên sự khác biệt, khi tôi sử dụng FOR UPDATE OF SAL hoặc chỉ cần viết FOR UPDATE.Sự khác biệt giữa CẬP NHẬT VÀ CẬP NHẬT

Theo O'Reilly

Các HÀNH danh sách các khoản CẬP NHẬT CHO không hạn chế bạn thay đổi chỉ những cột liệt kê. Khóa vẫn được đặt trên tất cả các hàng; danh sách OF chỉ cung cấp cho bạn một cách để ghi rõ hơn những gì bạn dự định thay đổi . Nếu bạn chỉ đơn giản là trạng thái FOR UPDATE trong truy vấn và không bao gồm một hoặc nhiều cột sau từ khóa OF, thì cơ sở dữ liệu sau đó sẽ khóa tất cả các hàng đã xác định trên tất cả các bảng được liệt kê trong mệnh đề FROM.

Có nghĩa là, khi tôi chỉ định tên cột với FOR UPDATE OF SAL, người dùng khác chỉ có thể thay đổi với cột SAL. Nhưng, thực tế, đây không phải là trường hợp. Tôi vẫn bị khóa trong phiên khác. Bất cứ ai có thể giải thích sự khác biệt.

CẬP NHẬT

----- 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 

Trả lời

14

Từ Oracle documentation:

Sử dụng mệnh đề OF ... cột để khóa các hàng chọn duy nhất cho một bảng cụ thể hoặc xem trong một tham gia. Các cột trong mệnh đề OF chỉ cho biết các hàng hoặc bảng nào bị khóa. Các cột cụ thể mà bạn chỉ định không đáng kể. Tuy nhiên, bạn phải chỉ định một tên cột thực tế là , không phải là bí danh cột. Nếu bạn bỏ qua mệnh đề này, thì cơ sở dữ liệu sẽ khóa các hàng đã chọn từ tất cả các bảng trong truy vấn.

Nếu truy vấn của bạn tham chiếu đến một bảng duy nhất thì không có sự khác biệt giữa FOR UPDATEFOR UPDATE OF ..., nhưng sau này vẫn có thể hữu ích như tự tài liệu hướng dẫn để biết cột nào bạn có ý định để cập nhật. Nó không hạn chế những gì bạn có thể cập nhật mặc dù. Nếu bạn có:

CURSOR cur IS SELECT * FROM emp FOR UPDATE OF sal; 

sau đó bạn vẫn có thể làm:

UPDATE emp SET comm = comm * 1.1 WHERE CURRENT OF cur; 

Nhưng nếu có nhiều hơn một bảng sau đó FOR UPDATE OF ... sẽ chỉ khóa các hàng trong bảng có chứa các cột bạn chỉ định trong Điều khoản OF.

Trái với những gì tôi nghĩ bạn đang nói trong câu hỏi. chỉ định FOR UPDATE OF sal không chỉ khóa cột sal; bạn không bao giờ có thể khóa một cột, khóa tối thiểu ở mức hàng. (Read more about locks). Nó khóa tất cả các hàng trong bảng chứa cột SAL, được chọn bởi truy vấn.


Trong bản cập nhật cho câu hỏi của bạn, truy vấn con trỏ của bạn sẽ tham gia empdept, nhưng mệnh đề OF chỉ có sal, một cột trong bảng emp.Các hàng trong bảng emp sẽ bị khóa khi con trỏ được mở và các khóa đó sẽ không được giải phóng cho đến khi bạn commit hoặc rollback phiên đó. Trong vòng lặp con trỏ, bạn có thể làm:

UPDATE emp SET ... WHERE CURRENT OF emp_cur; 

... để cập nhật hàng trong bảng emp liên quan đến vòng lặp này của vòng lặp. Bạn không có thể làm:

UPDATE dept SET ... WHERE CURRENT OF emp_cur; 

... vì hàng trong bảng dept không khóa, vì không có các cột là trong OF. Điều đó cũng có nghĩa là trong phiên thứ hai của bạn, các hàng dept có thể được cập nhật một cách tự do, vì chúng không bị khóa bởi phiên đầu tiên.

+0

Không, ý tôi muốn nói là, nó sẽ cho phép tôi cập nhật khi tôi sẽ cố cập nhật cột khác. Thậm chí, tôi tham gia hai bảng, nhưng vẫn kịch bản tương tự. Vui lòng kiểm tra bài đăng cập nhật của tôi và vui lòng giải thích. – Ravi

+0

@jWeavers - bạn không thể cập nhật một cột trong bảng nếu bảng đó không có tham chiếu trong mệnh đề 'OF'. Sử dụng 'WHERE CURRENT OF', dù sao thì không có gì ngăn bạn cập nhật bất cứ thứ gì bạn thích với một' UPDATE' bình thường mà không có mệnh đề đó - bao gồm trong các bảng bạn đã khóa với 'FOR UPDATE', vì bạn giữ khóa đó. –

+0

@jWeavers - từ bản cập nhật của bạn: phải, bạn đã khóa hàng ** ** trong 'emp', vì vậy phiên thứ hai phải đợi phiên đầu tiên giải phóng khóa (' commit'/'rollback'), mặc dù không có cập nhật nào được thực hiện. Phiên thứ hai của bạn vẫn có thể cập nhật 'dept', vì không có cột nào từ bảng đó nằm trong mệnh đề' OF'. –

0

một nhận xét bổ sung để cập nhật. Nếu bạn chọn từ nhiều bảng và không có mệnh đề where để tham chiếu mỗi bảng cho bản cập nhật thì nó sẽ khóa tất cả các bảng cho đến khi quá trình cập nhật hoàn tất.