Обратите внимание, что в предыдущем примере оператор COMMIT выполняется после окончания цикла выборки. Дело в том, что этот оператор снимает все блокировки, удерживаемые сеансом. Конструкция FOR UPDATE устанавливает блокировки, а оператор COMMIT их снимает.
Когда это происходит, действие курсора прекращается и любая последующая попытка считать строки приводит к ошибке Oracle:
Таким образом, если оператор COMMIT расположен внутри цикла выборки SELECT...FOR UPDATE, считывание строк после COMMIT будет завершаться ошибкой. Поэтому не рекомендуется размещать COMMIT внутри цикла. Если курсор не определен как SELECT...FOR UPDATE, никаких проблем не возникает.
Совет
Даже если не используется SELECT...FOR UPDATE, применение оператора COMMIT внутри цикла выборки нежелательно. Например, если запрос воздействует на большое число строк, то можно получить ошибку "ORA-1555snapshot too old" (мгновенный снимок слишком старый).
Как поступить, если требуется обновить строку, только что считанную из курсора, и при этом применить оператор COMMIT внутри цикла? Конструкцией WHERE CURRENT OF воспользоваться нельзя, так как курсор не может быть определен как FOR UPDATE. В этом случае можно использовать первичный ключ таблицы в условии WHERE оператора UPDATE,
как показано в следующем примере:
В этом примере, по существу, имитируется конструкция WHERE CURRENT OF, однако строки активного набора не блокируются. Как следствие, этот блок может выполняться не так, как требуется, если другие сеансы будут параллельно обращаться к данным.
Совет
Если используемая в запросе таблица не имеет первичного ключа, вместо него можно применить псевдостолбец ROWID. Можно извлечь ROWID каждого столбца в переменную PL/SQL (типа ROWID или UROWID) и использовать его в предложении WHERE в виде WHERE rowid = v_RowID.
< Предыдущая | Следующая > |
---|