PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Come fare in modo che PostgreSQL inserisca una riga in una tabella quando viene eliminata da un'altra tabella?

Scrivi una funzione di attivazione. Qualcosa del genere:

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 un trigger ON DELETE . In questo modo:

CREATE TRIGGER delaft
  AFTER DELETE
  ON tbl
  FOR EACH ROW
  EXECUTE PROCEDURE trg_backup_row();

Elementi chiave

  • È meglio che sia un trigger AFTER DELETE e FOR EACH ROW .

  • Per restituire tutte le colonne della vecchia tabella, usa la sintassi (OLD).* . Consulta il manuale sull'accesso ai tipi compositi . In alternativa OLD.* è anche una sintassi valida, perché OLD viene aggiunto a FROM clausola implicitamente. Per un VALUES espressione dovrebbe essere (OLD).* , anche se. Come:

    INSERT INTO other_tbl
    VALUES((OLD).*, some_variable)
    
  • Puoi includere valori da qualsiasi altra tabella come dimostro. Assicurati solo di ottenere una singola riga o di creare più voci.

  • Quando il trigger si attiva AFTER l'evento, la funzione può RETURN NULL .

Informazioni sulla visibilità

In risposta al commento attento di @couling.

Mentre le chiavi esterne possono essere dichiarate come DEFERRED , questo differirà solo il controllo di integrità, non l'eliminazione stessa. Righe che vengono eliminate nei trigger eseguiti prima di quello a portata di mano o da ON DELETE CASCADE le chiavi esterne non saranno più visibili al momento questo AFTER DELETE viene chiamato il trigger. (Succede tutto in una transazione ovviamente. Nessuno di questi dettagli è importante per altre transazioni, che vedranno tutti o nessuno degli effetti. Fare riferimento al manuale per ulteriori informazioni su Modello MVCC e isolamento delle transazioni .)

Pertanto, se vuoi includere i valori delle righe che dipendono in questo modo nel tuo INSERT , assicurati di chiamare questo attivatore prima quelle righe vengono eliminate.

Potrebbe essere necessario eseguire questo trigger BEFORE DELETE .

Oppure può significare che devi ordinare i tuoi trigger di conseguenza, BEFORE i trigger vengono prima di AFTER trigger, ovviamente. E i trigger allo stesso livello vengono eseguiti in ordine alfabetico .

Tuttavia, fintanto che sono super preciso qui, potrei anche aggiungere le modifiche apportate alla riga (o righe dipendenti) in altri BEFORE i trigger sono visibili solo se vengono chiamati prima questo.

Il mio consiglio di renderlo un AFTER trigger è dovuto al fatto che è meno soggetto a complicazioni ed è più economico se un altro trigger potrebbe annullare (ripristinare) il DELETE a metà dell'operazione, purché non si applichi nessuna delle precedenti.