sql >> Database >  >> RDS >> PostgreSQL

Hoe laat ik PostgreSQL een rij invoegen in een tabel wanneer deze uit een andere tabel wordt verwijderd?

Schrijf een triggerfunctie. Zoiets als dit:

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;

En een trigger ON DELETE . Zoals dit:

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

Belangrijke elementen

  • Maak er het beste een trigger AFTER DELETE en FOR EACH ROW .

  • Om alle kolommen uit de oude tabel terug te geven, gebruikt u de syntaxis (OLD).* . Zie de handleiding over toegang tot samengestelde typen . Als alternatief OLD.* is ook een geldige syntaxis, omdat OLD wordt toegevoegd aan de FROM clausule impliciet. Voor een VALUES uitdrukking zou moeten zijn (OLD).* , hoewel. Vind ik leuk:

    INSERT INTO other_tbl
    VALUES((OLD).*, some_variable)
    
  • U kunt waarden uit elke andere tabel opnemen, zoals ik laat zien. Zorg ervoor dat u een enkele rij krijgt, of u maakt meerdere vermeldingen.

  • Terwijl de trekker AFTER afgaat de gebeurtenis, de functie kan RETURN NULL .

Over zichtbaarheid

Als reactie op de waakzame opmerking van @couling.

Hoewel buitenlandse sleutels kunnen worden gedeclareerd als DEFERRED , zal dit alleen de integriteitscontrole uitstellen, niet de verwijdering zelf. Rijen die worden verwijderd in triggers die worden uitgevoerd vóór de vorige of door ON DELETE CASCADE buitenlandse sleutels zullen niet meer zichtbaar zijn op het moment dat deze AFTER DELETE trigger wordt genoemd. (Het gebeurt natuurlijk allemaal in één transactie. Geen van deze details is van belang voor andere transacties, die alle of geen van de effecten zullen zien. Raadpleeg de handleiding voor meer informatie over de MVCC-model en transactie-isolatie .)

Daarom, als u waarden uit rijen wilt opnemen die op een dergelijke manier afhankelijk zijn in uw INSERT , zorg ervoor dat u deze trigger voor . aanroept die rijen worden verwijderd.

Mogelijk moet u deze trigger BEFORE DELETE . maken .

Of het kan betekenen dat u uw triggers dienovereenkomstig moet bestellen, BEFORE triggers komen voor AFTER triggers natuurlijk. En triggers op hetzelfde niveau worden uitgevoerd in alfabetische volgorde .

Maar zolang ik hier super precies ben, zou ik ook kunnen toevoegen dat de wijzigingen die zijn aangebracht in de rij (of afhankelijke rijen) in andere BEFORE triggers zijn ook alleen zichtbaar als deze voor . worden genoemd deze.

Mijn advies om er een AFTER van te maken trigger was omdat het minder vatbaar is voor complicaties en goedkoper als een andere trigger de DELETE zou kunnen annuleren (terugdraaien) halverwege de operatie - zolang geen van bovenstaande van toepassing is.



  1. Database maken met behulp van een opgeslagen functie

  2. Oracle DB naar EF werkt niet correct voor NUMBER (2,0)

  3. Waarden doorgeven aan MySQL IN-bewerking in door PDO voorbereide instructie?

  4. Waarom is het het beste om een ​​telefoonnummer op te slaan als een string versus een geheel getal?