O Postgres suporta transações aninhadas, mas elas diferem do SQL convencional, mais como transações com pontos parciais aninhados.
No nível superior, você sempre tem seu típico
BEGIN/COMMIT/ROLLBACK
, e em níveis aninhados você deve usar os seguintes comandos:SAVEPOINT name
- cria um novo ponto de salvamento, com nome exclusivo para a transaçãoRELEASE SAVEPOINT name
- confirma o ponto de salvamento, embora ele só persista se a transação que a contém for confirmadaROLLBACK TO SAVEPOINT name
- reverte o ponto de salvamento
Você também teria que se certificar de que:
- Os nomes usados para cada
SAVEPOINT
são únicos; - Falha em um
SAVEPOINT
é propagado para cima até o nível superior.
A última parte é um pouco complicada, a menos que você use uma biblioteca que possa fazer isso automaticamente.
Quando escrevi pg-promise, certifiquei-me de que essas duas cláusulas fossem garantidas:
- Ele gera nomes de pontos de salvamento automaticamente, como
level_1
,level_2
, e assim por diante, com base no nível da transação; - Executa contendo
ROLLBACK TO SAVEPOINT name
, mais oROLLBACK
de nível superior caso uma transação filha falhe - tudo baseado na lógica de cadeia de promessas padrão.
Veja também as limitações das transações aninhadas do PostgreSQL explicadas...