PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Como fazer o PostgreSQL inserir uma linha em uma tabela quando excluída de outra tabela?


Escreva uma função de gatilho. Algo assim:
CREATE OR REPLACE FUNCTION trg_backup_row()
  RETURNS trigger AS
$BODY$
BEGIN

INSERT INTO other_tbl
SELECT (OLD).*, t.other_col                -- all columns of from old table
-- SELECT OLD.col1, OLD.col2, t.other_col  -- alternative: some cols from old tbl
FROM   third_tbl t
WHERE  t.col = OLD.col  -- link to third table with info from deleted row
AND    <unique_condition_to_avoid_multiple_rows_if_needed>;

RETURN NULL;

END;
$BODY$
  LANGUAGE plpgsql VOLATILE;

E um gatilho ON DELETE . Assim:
CREATE TRIGGER delaft
  AFTER DELETE
  ON tbl
  FOR EACH ROW
  EXECUTE PROCEDURE trg_backup_row();

Elementos-chave


  • Melhor torná-lo um trigger AFTER DELETE e PARA CADA LINHA .

  • Para retornar todas as colunas da tabela antiga, use a sintaxe (OLD).* . Consulte o manual sobre como acessar tipos compostos . Como alternativa OLD.* também é uma sintaxe válida, porque OLD é adicionado ao FROM cláusula implicitamente. Para um VALUES expressão teria que ser (OLD).* , no entanto. Curti:
    INSERT INTO other_tbl
    VALUES((OLD).*, some_variable)
    

  • Você pode incluir valores de qualquer outra tabela como demonstro. Apenas certifique-se de obter uma única linha ou crie várias entradas.

  • À medida que o gatilho dispara AFTER o evento, a função pode RETURN NULL .

Sobre visibilidade


Em resposta ao comentário atento de @couling.

Enquanto as chaves estrangeiras podem ser declaradas como DEFERRED , isso apenas adiará a verificação de integridade, não a exclusão em si. Linhas que são excluídas em gatilhos executados antes do que está em mãos ou por ON DELETE CASCADE chaves estrangeiras não serão mais visíveis no momento em que APÓS EXCLUIR gatilho é chamado. (Tudo acontece em uma transação, obviamente. Nenhum desses detalhes importa para outras transações, que verão todos ou nenhum dos efeitos. Consulte o manual para saber mais sobre o Modelo MVCC e isolamento de transações .)

Portanto, se você deseja incluir valores de linhas dependendo dessa maneira em seu INSERT , certifique-se de chamar esse acionador antes essas linhas são excluídas.

Você pode ter que fazer este gatilho BEFORE DELETE .

Ou pode significar que você precisa ordenar seus gatilhos de acordo, ANTES os gatilhos vêm antes de AFTER gatilhos, obviamente. E os gatilhos no mesmo nível são executados em ordem alfabética .

No entanto, desde que eu seja super preciso aqui, também posso adicionar as alterações feitas na linha (ou linhas dependentes) em outro ANTES os gatilhos também só são visíveis se forem chamados antes Este.

Meu conselho para torná-lo um DEPOIS gatilho foi porque é menos propenso a complicações e mais barato se outro gatilho puder cancelar (reverter) o DELETE no meio da operação - desde que nenhuma das opções acima se aplique.