PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Comment faire en sorte que PostgreSQL insère une ligne dans une table lorsqu'elle est supprimée d'une autre table ?

Écrire une fonction déclencheur. Quelque chose comme ça :

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;

Et un déclencheur ON DELETE . Comme ceci :

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

Éléments clés

  • Le mieux est d'en faire un déclencheur AFTER DELETE et FOR EACH ROW .

  • Pour renvoyer toutes les colonnes de l'ancienne table, utilisez la syntaxe (OLD).* . Voir le manuel sur l'accès aux types composites . Alternativement OLD.* est également une syntaxe valide, car OLD est ajouté au FROM clause implicitement. Pour un VALUES expression, il devrait être (OLD).* , pourtant. Comme :

    INSERT INTO other_tbl
    VALUES((OLD).*, some_variable)
    
  • Vous pouvez inclure des valeurs de n'importe quelle autre table comme je le démontre. Assurez-vous simplement d'obtenir une seule ligne, sinon vous créez plusieurs entrées.

  • Lorsque le déclencheur se déclenche AFTER l'événement, la fonction peut RETURN NULL .

À propos de la visibilité

En réponse au commentaire vigilant de @couling.

Alors que les clés étrangères peuvent être déclarées comme DEFERRED , cela ne fera que différer le contrôle d'intégrité, pas la suppression elle-même. Lignes supprimées dans les déclencheurs exécutés avant celui en cours ou par ON DELETE CASCADE les clés étrangères ne seront plus visibles au moment où cet AFTER DELETE le déclencheur est appelé. (Tout se passe évidemment en une seule transaction. Aucun de ces détails n'a d'importance pour les autres transactions, qui verront tout ou aucun des effets. Reportez-vous au manuel pour en savoir plus sur le Modèle MVCC et isolation des transactions .)

Par conséquent, si vous souhaitez inclure des valeurs de lignes dépendant de cette manière dans votre INSERT , assurez-vous d'appeler ce déclencheur avant ces lignes sont supprimées.

Vous devrez peut-être faire ce déclencheur BEFORE DELETE .

Ou cela peut signifier que vous devez ordonner vos déclencheurs en conséquence, BEFORE les déclencheurs viennent avant AFTER déclencheurs, évidemment. Et les déclencheurs au même niveau sont exécutés dans ordre alphabétique .

Cependant, tant que je suis super précis ici, je pourrais également ajouter que les modifications apportées à la ligne (ou aux lignes dépendantes) dans d'autres BEFORE les déclencheurs ne sont également visibles que s'ils sont appelés avant celui-ci.

Mon conseil pour en faire un AFTER le déclencheur était parce qu'il est moins sujet aux complications et moins cher si un autre déclencheur pouvait annuler (annuler) le DELETE à mi-chemin de l'opération - tant qu'aucune des conditions ci-dessus ne s'applique.