41.8. Gerenciamento de transação #

Tanto em procedimentos chamados pelo comando CALL, quanto em blocos de código anônimos (comando DO), é possível finalizar as transações usando os comandos COMMIT e ROLLBACK. Uma nova transação é iniciada automaticamente após o término de uma transação que usa estes comandos, portanto, não existe comando START TRANSACTION separado. (Note que BEGIN e END possuem significados diferentes no PL/pgSQL.)

A seguir está um exemplo simples:

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();

Uma nova transação começa com as características de transação padrão, como o nível de isolamento da transação. Nos casos em que as transações são efetivadas de maneira cíclica, pode-se desejar iniciar as novas transações automaticamente com as mesmas características da anterior. Os comandos COMMIT AND CHAIN e ROLLBACK AND CHAIN fazem isto.

O controle de transação só é possível em chamadas para CALL ou DO feitas a partir do nível mais alto, ou chamadas para CALL ou DO aninhadas sem qualquer outro comando interveniente. Por exemplo, se a pilha de chamadas for CALL proc1()CALL proc2()CALL proc3(), então o segundo e terceiro procedimentos podem executar ações de controle de transação. Mas se a pilha de chamadas for CALL proc1()SELECT func2()CALL proc3(), então o último procedimento não pode fazer controle de transação, devido ao SELECT no meio.

PL/pgSQL não tem suporte para pontos de salvamento (comandos SAVEPOINT/ROLLBACK TO SAVEPOINT/RELEASE SAVEPOINT). Os padrões de uso típicos para pontos de salvamento podem ser substituídos por blocos com tratadores de exceção (veja Captura de erros). Internamente, um bloco com tratadores de exceção forma uma subtransação, o que significa que as transações não podem ser finalizadas dentro desse bloco.

Considerações especiais se aplicam aos laços de cursor. Veja este exemplo:

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();

Normalmente, os cursores são fechados automaticamente na efetivação da transação. Entretanto, um cursor criado como parte de um laço como este é automaticamente convertido em cursor persistente (holdable) pelo primeiro COMMIT ou ROLLBACK, significando que o cursor é totalmente avaliado no primeiro COMMIT ou ROLLBACK, em vez de linha por linha. O cursor ainda é removido automaticamente após o laço, então isto é praticamente invisível para o usuário. Mas é preciso ter em mente que quaisquer bloqueios de tabela ou de linha obtidos pela consulta do cursor não serão mais mantidos após a primeira execução do COMMIT ou do ROLLBACK.

Não são permitidos comandos de controle de transação em laços de cursor acionados por comandos que não são de leitura apenas (por exemplo, UPDATE ... RETURNING).