43.8. Управление транзакциями
В процедурах, вызываемых командой 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();Управление транзакциями возможно только в вызовах CALL или DO в коде верхнего уровня или во вложенных CALL или DO без других промежуточных команд. Например, в стеке вызовов CALL proc1() → CALL proc2() → CALL proc3() вторая и третья процедуры могут управлять транзакциями. Но в стеке CALL proc1() → SELECT func2() → CALL proc3() последняя процедура лишена этой возможности из-за промежуточного SELECT.
Циклам с курсорами присущи некоторые особенности. Рассмотрите этот пример:
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, а не для каждой очередной строки. При этом он автоматически удаляется после цикла, так что это происходит практически незаметно для пользователя.
Команды управления транзакциями не допускаются в циклах с курсором, которыми управляют запросы, производящие не только чтение, но и модификацию данных (например, UPDATE ... RETURNING).
Транзакция не может завершаться внутри блока с обработчиками исключений.