В процедурах, вызываемых с помощью CALL команды
а также в анонимных блоках кода (командаDO ),
можно завершать транзакции, используя
команды COMMIT и ROLLBACK. Новая
транзакция инициируется автоматически после завершения транзакции с помощью
этих команд, поэтому отдельная команда START
TRANSACTION не требуется. (Обратите внимание, что BEGIN и
END имеют разные значения в PL/pgSQL.)
Ниже приведен простой пример:
CREATE PROCEDURE transaction_test1()
LANGUAGE plpgsql
AS $$
BEGIN
FOR i IN 0..9 LOOP
INSERT INTO test1 (a) VALUES (i);
IF i % 2 = 0 THEN
COMMIT;
ELSE
ROLLBACK;
END IF;
END LOOP;
END;
$$;
CALL transaction_test1();
Новая транзакция начинается с характеристиками транзакции по умолчанию, такими как уровень изоляции. В случаях, когда фиксация транзакций происходит в цикле, может потребоваться автоматический запуск новых транзакций с теми же характеристиками, что и у предыдущей. Это позволяют реализовать команды
COMMIT AND CHAIN и ROLLBACK AND
CHAIN accomplish this.
Управление транзакциями возможно только в CALL или
DO вызовах с верхнего уровня, либо во вложенных
CALL или DO вызовы без каких-либо других промежуточных команд. Например, если стек вызовов имеет вид:
CALL proc1() → CALL proc2()
→ CALL proc3(), то вторая и третья процедуры могут выполнять действия по управлению транзакциями. Но если стек вызовов
имеет вид CALL proc1() → SELECT
func2() → CALL proc3(), то последняя
процедура не может управлять транзакциями из-за
SELECT между ними.
PL/pgSQL не поддерживает точки сохранения
(SAVEPOINT/ROLLBACK TO
SAVEPOINT/RELEASE SAVEPOINT команд).
Типовые сценарии использования точек сохранения могут быть заменены блоками с
обработчиками исключений (см. Раздел 5.6.6.8). Внутренне блок с обработчиками исключений формирует подтранзакцию, что означает невозможность завершения транзакций внутри такого блока.
Особые условия применяются к циклам по курсору. Рассмотрим следующий пример:
CREATE PROCEDURE transaction_test2()
LANGUAGE plpgsql
AS $$
DECLARE
r RECORD;
BEGIN
FOR r IN SELECT * FROM test2 ORDER BY x LOOP
INSERT INTO test1 (a) VALUES (r.x);
COMMIT;
END LOOP;
END;
$$;
CALL transaction_test2();
Обычно курсоры автоматически закрываются при фиксации транзакции. Однако курсор, созданный как часть подобного цикла, автоматически преобразуется в удерживаемый курсор при выполнении первой команды COMMIT или
ROLLBACK. Это означает, что курсор полностью вычисляется при первом COMMIT или
ROLLBACK , а не построчно. Курсор по-прежнему удаляется автоматически после завершения цикла, поэтому для пользователя это практически незаметно. Однако следует учитывать, что любые блокировки таблиц или строк, установленные запросом курсора, больше не будут удерживаться после первого COMMIT или
ROLLBACK.
Команды управления транзакциями не разрешены в циклах курсора, инициированных командами, которые не являются операциями только для чтения (например, UPDATE
... RETURNING).