PostgreSQL La base de donnees la plus sophistiquee au monde.

Forums PostgreSQL.fr

Le forum officiel de la communauté francophone de PostgreSQL

Vous n'êtes pas identifié(e).

#1 28/03/2018 17:39:40

bruhnil
Membre

Impossible de supprimer une entité avec un trigger

Bonjour,

Je dois mettre à jour une table dashboard.t_suivi à partir de la table coordination.numerisation.

CREATE OR REPLACE FUNCTION update_t_suivi() RETURNS TRIGGER AS $$
BEGIN
INSERT INTO dashboard.t_suivi  ( 
  id_coord, 
  lot, 
  cdd,
  mission_moe,
  id_prog, 
  id_nro, 
  numero,
  insee, 
  com_dep, 
  statut, 
  emprise, 
  nom, 
  travaux, 
  longueur, 
  debut_trvx, 
  prog_dsp, 
  moa, 
  commentair, 
  envoi_moe
)
VALUES(
 new.id_opp, 
  new.lot, 
  new.cdd,
  new.phase,
  new.id_prog, 
  new.id_nro,  
  new.numero,
  new.insee, 
  new.com_dep, 
  new.statut, 
  new.emprise, 
  new.nom, 
  new.travaux, 
  new.longueur, 
  new.debut_trvx, 
  new.prog_dsp, 
  new.moa, 
  new.commentair, 
  new.envoi_moe)
;
  RETURN NEW;
END;
$$ LANGUAGE 'plpgsql';


DROP TRIGGER IF EXISTS trg_update_t_suivi ON coordination.numerisation;
CREATE TRIGGER trg_update_t_suivi
BEFORE INSERT OR DELETE OR UPDATE ON coordination.numerisation 
FOR EACH ROW
EXECUTE PROCEDURE update_t_suivi();

Lorsque je fais le test d'insérer une nouvelle entité dans la table coordination.numerisation, la ligne est bien automatiquement reportée dans la table dashboard.t_suivi, mais dès que je veux supprimer cette entité test dans la table numerisation, je reçois un message d’erreur : Impossible de valider les changements pour la couche Numérisation

Erreurs : ERREUR : 1 attribut non effacé.
 
Erreur du fournisseur de données :
      Erreur PostGIS lors de la suppression d'entité : ERREUR:  l'enregistrement « new » n'est pas encore affectée
    DETAIL:  La structure de ligne d'un enregistrement pas encore affecté est indéterminée.

Pourriez vous me dire ce qui cloche dans mon ma requete?

Merci d'avance!

Hors ligne

#2 28/03/2018 17:44:30

gleu
Administrateur

Re : Impossible de supprimer une entité avec un trigger

Vous utilisez un trigger BEFORE, donc il est déclenché avant la réalisation de l'opération, donc la variable NEW ne contient aucune information. Vous devez utiliser un trigger AFTER. Voir https://www.postgresql.org/docs/10/stat … anges.html.


Guillaume.

Hors ligne

#3 29/03/2018 11:28:29

bruhnil
Membre

Re : Impossible de supprimer une entité avec un trigger

Merci gleu pour la réponse,

J'ai modifié le trigger avec un AFTER et j'arrive bien cette fois à supprimer l'entité rajoutée dans la table coordination.numerisation mais la ligne apparait toujours dans la table dashboard.t_suivi.
La c

DROP TRIGGER IF EXISTS trg_update_t_suivi ON dashboard.t_suivi;
DROP TRIGGER IF EXISTS trg_update_t_suivi ON coordination.numerisation;
CREATE TRIGGER trg_update_t_suivi
AFTER UPDATE ON coordination.numerisation 
FOR EACH ROW
WHEN (OLD.* IS DISTINCT FROM NEW.*)
EXECUTE PROCEDURE update_t_suivi();

et si je rajoute les conditions DELETE et INSERT

DROP TRIGGER IF EXISTS trg_update_t_suivi ON dashboard.t_suivi;
DROP TRIGGER IF EXISTS trg_update_t_suivi ON coordination.numerisation;
CREATE TRIGGER trg_update_t_suivi
AFTER INSERT OR DELETE OR UPDATE ON coordination.numerisation 
FOR EACH ROW
WHEN (OLD.* IS DISTINCT FROM NEW.*)
EXECUTE PROCEDURE update_t_suivi();

je reçois cette erreur:

ERROR:  ERREUR:  la condition WHEN du trigger INSERT ne peut pas référencer les valeurs OLD
LINE 6: WHEN (OLD.* IS DISTINCT FROM NEW.*)

Hors ligne

#4 29/03/2018 14:18:51

gleu
Administrateur

Re : Impossible de supprimer une entité avec un trigger

J'ai modifié le trigger avec un AFTER et j'arrive bien cette fois à supprimer l'entité rajoutée dans la table coordination.numerisation mais la ligne apparait toujours dans la table dashboard.t_suivi.

Vous renvoyez la valeur NEW, donc c'est normal. Voir https://www.postgresql.org/docs/10/stat … ML-TRIGGER pour les détails.

et si je rajoute les conditions DELETE et INSERT je reçois cette erreur:

ERROR:  ERREUR:  la condition WHEN du trigger INSERT ne peut pas référencer les valeurs OLD

Oui, OLD n'est pas référençable pour un INSERT, vu qu'il n'y a pas d'ancienne version de la ligne. Tout comme NEW n'est pas référençable pour un DELETE.


Guillaume.

Hors ligne

#5 29/03/2018 16:00:21

bruhnil
Membre

Re : Impossible de supprimer une entité avec un trigger

Merci pour ce retour.
J'ai trouvé une astuce permettant de faire ce que je voulais.
Je passe par deux triggers:

Le premier permet de rajouter ou mettre à jour les lignes de coordination.numerisation dans dashboard.t_suivi.

CREATE OR REPLACE FUNCTION update_t_suivi() RETURNS TRIGGER AS $$
BEGIN
INSERT INTO dashboard.t_suivi  ( 
  id_coord, 
  lot, 
  cdd,
  mission_moe,
  id_prog, 
  id_nro, 
  numero,
  insee, 
  com_dep, 
  statut, 
  emprise, 
  nom, 
  travaux, 
  longueur, 
  debut_trvx, 
  prog_dsp, 
  moa, 
  commentair, 
  envoi_moe
)
VALUES(
 new.id_opp, 
  new.lot, 
  new.cdd,
  new.phase,
  new.id_prog, 
  new.id_nro,  
  new.numero,
  new.insee, 
  new.com_dep, 
  new.statut, 
  new.emprise, 
  new.nom, 
  new.travaux, 
  new.longueur, 
  new.debut_trvx, 
  new.prog_dsp, 
  new.moa, 
  new.commentair, 
  new.envoi_moe)
;
  RETURN NEW;
END;
$$ LANGUAGE 'plpgsql';



DROP TRIGGER IF EXISTS trg_update_t_suivi_num ON dashboard.t_suivi;
DROP TRIGGER IF EXISTS trg_update_t_suivi_num ON coordination.numerisation;
CREATE TRIGGER trg_update_t_suivi_num
AFTER UPDATE OR INSERT ON coordination.numerisation
FOR EACH ROW
EXECUTE PROCEDURE update_t_suivi();

Le deuxième trigger permet de supprimer les lignes de dashboard.t_suivi ne figurant pas ou plus dans coordination.numerisation.

CREATE OR REPLACE FUNCTION delete_t_suivi() RETURNS TRIGGER AS $$
BEGIN
 WITH a_supprimer AS
(
SELECT *
FROM dashboard.t_suivi AS num
WHERE num.id_coord  NOT IN  
(SELECT DISTINCT id_opp
FROM coordination.numerisation  opp
WHERE id_coord=id_opp
GROUP BY id_coord, id_opp
))
DELETE FROM dashboard.t_suivi a
USING a_supprimer b
WHERE a.id = b.id;

  RETURN NEW;
END;
$$ LANGUAGE 'plpgsql';



DROP TRIGGER IF EXISTS trg_delete_t_suivi_num ON dashboard.t_suivi;
DROP TRIGGER IF EXISTS trg_delete_t_suivi_num ON coordination.numerisation;
CREATE TRIGGER trg_delete_t_suivi_num
AFTER UPDATE OR DELETE ON coordination.numerisation 
FOR EACH ROW
EXECUTE PROCEDURE delete_t_suivi();

Hors ligne

Pied de page des forums