Подтвердить что ты не робот

BEGIN - END блокирует атомные транзакции в PL/SQL

Эта информация должна быть легко найти, но мне не повезло.

Когда у меня есть блок BEGIN - END в PL/SQL, он ведет себя как атомная транзакция, которая будет пытаться зафиксировать при попадании в блок END, и если что-то пойдет не так, отбрасывает изменения?

Если нет, как я могу убедиться, что код внутри блока BEGIN-END ведет себя как атомная транзакция и как блок ведет себя "по умолчанию"?

EDIT: Я запускаюсь из хранимой процедуры, и я использую неявный блок, я думаю.

4b9b3361

Ответ 1

Во-первых, BEGIN..END являются просто синтаксическими элементами и не имеют ничего общего с транзакциями.

Во-вторых, в Oracle все отдельные операторы DML являются атомарными (т.е. они либо полностью преуспевают, либо откатывают любые промежуточные изменения при первом сбое) (если вы не используете опцию EXCEPTIONS INTO, в которую я не буду входить).

Если вы хотите, чтобы группа операторов обрабатывалась как одна атомная транзакция, вы сделали бы что-то вроде этого:

BEGIN
  SAVEPOINT start_tran;
  INSERT INTO .... ; -- first DML
  UPDATE .... ; -- second DML
  BEGIN ... END; -- some other work
  UPDATE .... ; -- final DML
EXCEPTION
  WHEN OTHERS THEN
    ROLLBACK TO start_tran;
    RAISE;
END;

Таким образом, любое исключение приведет к откату операторов в этом блоке, но любые операторы, которые выполнялись до этого блока, не будут отброшены назад.

Обратите внимание, что я не включаю COMMIT - обычно я предпочитаю, чтобы вызывающий процесс выдавал коммит.


Верно, что блок BEGIN..END без обработчика исключений автоматически обработает это для вас:

BEGIN
  INSERT INTO .... ; -- first DML
  UPDATE .... ; -- second DML
  BEGIN ... END; -- some other work
  UPDATE .... ; -- final DML
END;

Если возникает исключение, все вставки и обновления будут отброшены назад; но как только вы захотите добавить обработчик исключений, он не откатится. Поэтому я предпочитаю явный метод с использованием точек сохранения.

Ответ 2

Блоки

BEGIN - END являются строительными блоками PL/SQL, и каждая единица PL/SQL содержится, по меньшей мере, в одном таком блоке. Блокировка блоков BEGIN - END в блоках PL/SQL обычно выполняется, чтобы уловить некоторые исключения и обработать это специальное исключение и затем создать несвязанные исключения. Тем не менее, в PL/SQL вы (клиент) должны всегда вызывать фиксацию или откат для транзакции.

Если вы хотите иметь атомные транзакции в транзакции, содержащей PL/SQL, вам нужно объявить PRAGMA AUTONOMOUS_TRANSACTION в блоке объявления. Это гарантирует, что любой DML внутри этого блока может быть зафиксирован или откатан независимо от содержащейся транзакции.

Однако вы не можете объявить эту прагму для вложенных блоков. Вы можете объявить это только для:

  • Верхние (не вложенные) анонимные блоки PL/SQL
  • Элемент списка
  • Локальные, автономные и упакованные функции и процедуры.
  • Методы типа объекта SQL
  • Триггеры базы данных

Ссылка: Oracle

Ответ 3

Вы не упомянули, является ли это анонимным блоком PL/SQL или декларативным, т.е. Пакет, процедура или функция. Однако в PL/SQL необходимо явно указать COMMIT, чтобы сохранить транзакцию (транзакции) в базе данных. COMMIT фактически сохраняет все несохраненные транзакции в базе данных из текущего сеанса пользователя.

Если возникает ошибка, транзакция неявно выполняет ROLLBACK.

Это поведение по умолчанию для PL/SQL.