2013-04-18 3 views
6

Что имеет значение, когда я использую FOR UPDATE OF SAL или просто пишу FOR UPDATE.Разница между ОБНОВЛЕНИЕМ И ОБНОВЛЕНИЕМ

Согласно O'Reilly

The Перечня предложении UPDATE FOR не ограничивает вас к изменению только те столбцы в списке. Замки все еще размещены на всех строках; список 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 

ответ

14

От Oracle documentation:

Используйте ОГОВОРКУ OF ... колонки для блокировки выбора строк только для конкретной таблицы или представлений в объединении. Столбцы в предложении OF только указывают, какие таблицы или строки просмотра заблокированы. Конкретные столбцы , которые вы указали, несущественны. Однако вы должны указать фактическое имя столбца , а не псевдоним столбца. Если вы опускаете это предложение, то база данных блокирует выбранные строки из всех таблиц запроса.

Если запрос ссылается на одну таблицу, то нет никакой разницы между FOR UPDATE и FOR UPDATE OF ..., но последний все еще может быть полезным в качестве самостоятельной документации, чтобы указать, какие столбцы вы собираетесь обновить. Это не ограничивает того, что вы можете обновить. Если у вас есть:

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

, то вы все равно можете сделать:

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

Но если есть более чем одна таблица, то FOR UPDATE OF ... только блокирует строки таблиц, которые содержат столбцы, заданные в OF статья.

Вопреки тому, что я думаю, вы говорите в вопросе. с указанием FOR UPDATE OF sal не только фиксирует столбец sal; вы никогда не можете заблокировать один столбец, минимальная блокировка находится на уровне строки. (Read more about locks). Он блокирует все строки в таблице, которая содержит столбец SAL, которые выбираются по запросу.


В обновлении на ваш вопрос, курсор запроса присоединяется emp и dept, но пункт OF имеет только sal, столбец в таблице emp.Строки в таблице emp будут заблокированы при открытии курсора, и эти блокировки не будут освобождены до тех пор, пока вы не выполните commit или rollback этот сеанс. В вашей петле курсора вы можете сделать:

UPDATE emp SET ... WHERE CURRENT OF emp_cur; 

... обновить строку в таблице emp, которая относится к этой итерации цикла. Вы не можно сделать:

UPDATE dept SET ... WHERE CURRENT OF emp_cur; 

... потому что строки в таблице dept не блокируются, поскольку столбцы не были в OF. Это также означает, что во втором сеансе строки dept могут быть обновлены свободно, так как они не заблокированы первым сеансом.

+0

Нет, я хотел сказать, что это позволит мне обновить, когда я попытаюсь обновить другой столбец. Даже, я присоединяюсь к двум таблицам, но по-прежнему тем же сценариям. Пожалуйста, проверьте мое обновленное сообщение и объясните, пожалуйста. – Ravi

+0

@jWeavers - вы не сможете обновить столбец в таблице, если эта таблица не имеет ссылок в предложении 'OF'. В любом случае, используя 'WHERE CURRENT OF', вам нечего обновлять что-либо, что вам нравится, с помощью обычного' UPDATE' без этого предложения, в том числе в таблицах, которые вы заблокировали с помощью 'FOR UPDATE', поскольку вы держите эту блокировку. –

+0

@jWeavers - из вашего обновления: справа, вы заблокировали ** строку ** в 'emp', поэтому второй сеанс должен дождаться, когда первый сеанс освободит блокировки (' commit'/'rollback') хотя никаких обновлений не было сделано. Второй сеанс может обновить 'dept', хотя в столбце' OF' нет столбцов из этой таблицы. –

0

один дополнительный комментарий для обновления. Если вы выберете из нескольких таблиц и не имеете предложения where для ссылки на каждую таблицу для обновления, тогда он заблокирует все таблицы до тех пор, пока обновление не будет выполнено.

Смежные вопросы