PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Wie lässt sich PostgreSQL dazu bringen, eine Zeile in eine Tabelle einzufügen, wenn sie aus einer anderen Tabelle gelöscht wird?

Schreiben Sie eine Triggerfunktion. Etwa so:

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;

Und einen Trigger ON DELETE . So:

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

Schlüsselelemente

  • Machen Sie es am besten zu einem Trigger AFTER DELETE und FOR EACH ROW .

  • Um alle Spalten aus der alten Tabelle zurückzugeben, verwenden Sie die Syntax (OLD).* . Siehe das Handbuch zum Zugriff auf zusammengesetzte Typen . Alternativ OLD.* ist auch syntaktisch gültig, weil OLD wird zum FROM hinzugefügt Klausel implizit. Für einen VALUES Ausdruck müsste es (OLD).* sein , obwohl. Wie:

    INSERT INTO other_tbl
    VALUES((OLD).*, some_variable)
    
  • Sie können Werte aus jeder anderen Tabelle einschließen, wie ich es demonstriere. Stellen Sie einfach sicher, dass Sie eine einzelne Zeile erhalten, oder erstellen Sie mehrere Einträge.

  • Wenn der Trigger AFTER auslöst das Ereignis, kann die Funktion RETURN NULL .

Über Sichtbarkeit

Als Antwort auf den aufmerksamen Kommentar von @couling.

Während Fremdschlüssel als DEFERRED , verzögert dies nur die Integritätsprüfung, nicht das Löschen selbst. Zeilen, die in Triggern gelöscht werden, die vor dem vorliegenden oder ausgeführt werden durch ON DELETE CASCADE Fremdschlüssel sind nicht mehr sichtbar zum Zeitpunkt dieses AFTER DELETE Trigger aufgerufen wird. (Es passiert offensichtlich alles in einer Transaktion. Keines dieser Details ist für andere Transaktionen von Bedeutung, die alle oder keine der Auswirkungen sehen werden. Weitere Informationen zu MVCC-Modell und Transaktionsisolation .)

Wenn Sie also Werte aus so abhängigen Zeilen in Ihr INSERT aufnehmen möchten , stellen Sie sicher, dass Sie diesen Trigger vorher aufrufen diese Zeilen werden gelöscht.

Möglicherweise müssen Sie diesen Trigger BEFORE DELETE ausführen .

Oder es kann bedeuten, dass Sie Ihre Trigger entsprechend bestellen müssen, BEFORE Trigger kommen vor AFTER Auslöser, offensichtlich. Und Trigger auf derselben Ebene werden in alphabetischer Reihenfolge ausgeführt .

Solange ich hier jedoch sehr genau bin, kann ich auch hinzufügen, dass Änderungen an der Zeile (oder abhängigen Zeilen) in anderen BEFORE vorgenommen wurden Trigger sind auch nur sichtbar, wenn diese vorher aufgerufen werden dieses hier.

Mein Rat, es zu einem AFTER zu machen Auslöser war, weil er weniger anfällig für Komplikationen und billiger ist, wenn ein anderer Auslöser das DELETE abbrechen (zurücksetzen) könnte nach der Hälfte des Vorgangs - solange keiner der oben genannten Punkte zutrifft.