Nous utilisons des cookies pour vous garantir la meilleure expérience sur notre site. Si vous continuez à utiliser ce dernier, nous considèrerons que vous acceptez l'utilisation des cookies. J'ai compris ! ou En savoir plus !.
banniere

Le portail francophone de la géomatique


Toujours pas inscrit ? Mot de passe oublié ?
Nom d'utilisateur    Mot de passe              Toujours pas inscrit ?   Mot de passe oublié ?

Annonce

Suite à un problème technique intervenu entre le 22 et le 23 mars, nous avons du procéder dans la soirée du 25 mars, à la restauration de la base de données du 24 mars (matinée).

En clair, nous avons perdu vos contributions et inscriptions du dimanche 24 et du lundi 25 mars.
Nous vous prions de nous excuser.

#1 Mon 04 January 2021 16:33

tweaxy
Participant actif
Lieu: Abbeville
Date d'inscription: 27 Dec 2018
Messages: 76

Trigger suppression d'objets dans une table tierce

Bonjour,

Je souhaiterais à l'aide d'un trigger, lors d'une suppression d'un objet linéaire, supprimer également tous les objets d'une table de correspondance où une clé étrangère donne sur mon objet linéaire.
an_voie : des noms de voie.
an_section_voie : Table de correspondance entre mes linéaires et une ou plusieurs voie associée.
(Un linéaire peut en effet avoir une ou plusieurs voie liée, une association N,N dans un MCD)
geo_section_voie : Mes linéaires

A la suppression d'un linéaire de voie, je dois également supprimer tous les objets dans la table an_section_voie qui ont une valeur de mon ID de geo_section_voie.

En faisant un AFTER DELETE, je n'arrive pas à récupérer mon ID de mon linéaire.
En faisant un BEFORE DELETE, je n'ai pas non plus réussi...
Voilà mon code ci-dessous.
Ne vous préoccuper pas de la première partie, qui recalcule la longueur de la voie suite à une suppression d'objets dans la table de correspondance.

CREATE FUNCTION rva.delete_calcul_longueur_voie() RETURNS trigger AS $BODY$
    DECLARE
    v_long_delete real;
    v_id_delete integer;
   
begin
    IF (TG_TABLE_NAME = 'an_section_voie') THEN
        SELECT longueur FROM rva.an_voie WHERE id_voie = OLD.id_voie INTO v_long_delete;
        -- on recalcul la longueur avec le OLD.idvoie
        v_id_delete := OLD.id_voie; -- on récupère ancien id_voie associé
        v_long_delete := v_long_delete - (SELECT sum(st_length(s.geom)) FROM rva.geo_section_voie s, rva.an_section_voie sv
        WHERE sv.id_sectvoi = OLD.id_sectvoi AND s.id_section = sv.id_section);
        IF v_long_delete IS null THEN -- si null on met 0 (nécessaire car le null emporte sur le 0 sur l'opération v_long_old au dessus)
            v_long_delete := 0;
        END IF;
        UPDATE rva.an_voie SET longueur = v_long_delete WHERE id_voie = v_id_delete;
    END IF;   
   
    -- marche pas ça...
    IF (TG_TABLE_NAME = 'geo_section_voie') THEN
        DELETE FROM rva.an_section_voie WHERE id_section = OLD.id_section;
    END IF;
    return NEW;
end;
$BODY$ LANGUAGE plpgsql;


Et les triggers associés à cette fonction :

CREATE TRIGGER tr_calc_voies3 BEFORE DELETE ON rva.an_section_voie
    FOR EACH ROW EXECUTE PROCEDURE rva.delete_calcul_longueur_voie();
   
-- lui ne marche pas..
CREATE TRIGGER tr_calc_voies4 BEFORE DELETE ON rva.geo_section_voie
    FOR EACH ROW EXECUTE PROCEDURE rva.delete_calcul_longueur_voie();


Visiblement un besoin simple, que je n'arrive pas à faire....
Egalement, si je supprime les objets dans cette table de correpondance, est-ce que ma première partie de ma fonction trigger va se réaliser (sachant que pour chaque suppression d'objets dans la table an_section_voie, je lance cette procédure) ?

En espérant avoir été compréhensible dans ma demande smile

Merci d'avance

Léandre

Hors ligne

 

#2 Mon 04 January 2021 22:28

jmarsac
Participant assidu
Lieu: NICE
Date d'inscription: 26 Oct 2005
Messages: 566
Site web

Re: Trigger suppression d'objets dans une table tierce

Bonsoir,

Pas besoin de trigger, il faut simplement utiliser l'option ON DELETE CASCADE dans la définition de la colonne contenant la clé étrangère :

Code:

CREATE TABLE an_section_voie(
    id serial PRIMARY KEY,
    id_section integer REFERENCES geo_section_voie ON DELETE CASCADE,
    id_voie integer REFERENCES an_voie ON DELETE CASCADE
);

Tout enregistrement de la table de correspondance an_section_voie sera ainsi supprimé si la voie ou le linéaire auquel il fait référence est supprimé.
Le "ON DELETE CASCADE" sur id_voie n'était pas dans le besoin exprimé mais évite les "orphelins de voie".


Jean-Marie
Azimut

Hors ligne

 

#3 Tue 05 January 2021 08:47

tweaxy
Participant actif
Lieu: Abbeville
Date d'inscription: 27 Dec 2018
Messages: 76

Re: Trigger suppression d'objets dans une table tierce

Bonjour,

C'est ce que j'avais initialement tenté avec le code ci-dessous, mais si je supprime un objet linéaire de ma table geo_section_voie, ça ne supprime pas les objets dans an_section_voie là où cette section était liée...

ALTER TABLE rva.geo_section_voie
  ADD CONSTRAINT source_section_fkey FOREIGN KEY (source)
      REFERENCES rva.lt_source_section (code) MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE CASCADE;
      

ALTER TABLE rva.an_section_voie
  ADD CONSTRAINT id_section_fkey FOREIGN KEY (id_section)
      REFERENCES rva.geo_section_voie (id_section) MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE CASCADE,
  ADD CONSTRAINT id_voie_fkey FOREIGN KEY (id_voie)
      REFERENCES rva.an_voie (id_voie) MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE CASCADE,   
  ADD CONSTRAINT cote_voie_fkey FOREIGN KEY (cote_voie)
      REFERENCES rva.lt_cote_voie (code) MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE CASCADE;


Si je comprends bien, le ON DELETE CASCADE, si mis sur l'attribut id_voie de la table an_section_voie, si je supprime la voie dans ma table an_voie, ça va supprimer tous les objets liés dans la table an_section_voie, ou est-ce l'inverse, c'est-à-dire que si je supprime un objet dans an_section_voie, où le id_voie était 12 par exemple, ça va supprimer la voie dans an_voie ?


Merci à vous

Léandre

Hors ligne

 

#4 Tue 05 January 2021 08:54

tweaxy
Participant actif
Lieu: Abbeville
Date d'inscription: 27 Dec 2018
Messages: 76

Re: Trigger suppression d'objets dans une table tierce

Après lecture de cette doc, https://www.postgresqltutorial.com/post … reign-key/
comme vous le dites, ça devrait fonctionner, mais lorsque je tente de supprimer un objet, via QGIS ou même via une requête SQL, ça ne supprime rien..

Léandre

Dernière modification par tweaxy (Tue 05 January 2021 09:01)

Hors ligne

 

#5 Tue 05 January 2021 10:07

tweaxy
Participant actif
Lieu: Abbeville
Date d'inscription: 27 Dec 2018
Messages: 76

Re: Trigger suppression d'objets dans une table tierce

Bonjour,

Après quelques tests, sans les triggers mis en place pour d'autres besoins, le ON DELETE CASCADE fonctionne très bien...
J'ai donc un problème dans l'un des triggers généré.
Le problème vient de cette fonction trigger :


-- an_voie : longueur de la voie
CREATE FUNCTION rva.delete_calcul_longueur_voie() RETURNS trigger AS $BODY$
    DECLARE
    v_long_delete real;
    v_id_delete integer;
   
begin
    IF (TG_TABLE_NAME = 'an_section_voie') THEN
        SELECT longueur FROM rva.an_voie WHERE id_voie = OLD.id_voie INTO v_long_delete;
        -- on recalcul la longueur avec le OLD.idvoie
        v_id_delete := OLD.id_voie; -- on récupère ancien id_voie associé
        v_long_delete := v_long_delete - (SELECT sum(st_length(s.geom)) FROM rva.geo_section_voie s, rva.an_section_voie sv
        WHERE sv.id_sectvoi = OLD.id_sectvoi AND s.id_section = sv.id_section);
        IF v_long_delete IS null THEN -- si null on met 0 (nécessaire car le null emporte sur le 0 sur l'opération v_long_old au dessus)
            v_long_delete := 0;
        END IF;
        UPDATE rva.an_voie SET longueur = v_long_delete WHERE id_voie = v_id_delete;
    END IF;   
   
    -- marche pas ça...
    /*IF (TG_TABLE_NAME = 'geo_section_voie') THEN
        DELETE FROM rva.an_section_voie WHERE id_section = OLD.id_section;
    END IF;*/
    return NEW;
end;
$BODY$ LANGUAGE plpgsql;

CREATE TRIGGER tr_calc_voies3 BEFORE DELETE ON rva.an_section_voie
    FOR EACH ROW EXECUTE PROCEDURE rva.delete_calcul_longueur_voie();


Celle-ci empêche visiblement la suppression de mes objets qui étaient liées à ma section de voie..
Il s'agit pourtant d'un BEFORE DELETE, afin de recalculer la longueur de mes voies en faisant la somme des longueurs des sections associées à la voie..

Merci

Léandre

Hors ligne

 

#6 Tue 05 January 2021 13:06

jmarsac
Participant assidu
Lieu: NICE
Date d'inscription: 26 Oct 2005
Messages: 566
Site web

Re: Trigger suppression d'objets dans une table tierce

Bonjour,

Ce serait plutôt (non testé) :

Code:

CREATE FUNCTION rva.set_longueur_voie() RETURNS trigger AS $BODY$
   
BEGIN
   UPDATE rva.an_voie 
     SET longueur = (SELECT sum(st_length(geom)) FROM rva.geo_section_voie
         WHERE id_section IN (
         SELECT id_section FROM rva.an_section_voie WHERE id_voie =  OLD.id_voie
         ) )
    WHERE id_voie = OLD.id_voie;

    return OLD;
END;
$BODY$ LANGUAGE plpgsql;

NB: la valeur de retour du trigger AFTER est ignorée

Code:

CREATE TRIGGER tr_update_longueur_voie AFTER DELETE ON rva.an_section_voie
    FOR EACH ROW EXECUTE PROCEDURE rva.set_longueur_voie();

Dernière modification par jmarsac (Wed 06 January 2021 18:13)


Jean-Marie
Azimut

Hors ligne

 

#7 Wed 06 January 2021 11:21

tweaxy
Participant actif
Lieu: Abbeville
Date d'inscription: 27 Dec 2018
Messages: 76

Re: Trigger suppression d'objets dans une table tierce

Bonjour,

Après tests ce matin, ça fonctionne effectivement.

Je vous remercie.

Etant novice sur l'utilisation des triggers, si j'ai bien compris la logique, même sur un AFTER DELETE, on peut récupérer la valeur OLD d'un attribut de l'objet ? On doit par contre renvoyer le return OLD pour pouvoir effectuer d'autres triggers ???


Cordialement,
Léandre

Hors ligne

 

#8 Wed 06 January 2021 18:12

jmarsac
Participant assidu
Lieu: NICE
Date d'inscription: 26 Oct 2005
Messages: 566
Site web

Re: Trigger suppression d'objets dans une table tierce

tweaxy a écrit:

Etant novice sur l'utilisation des triggers, si j'ai bien compris la logique, même sur un AFTER DELETE, on peut récupérer la valeur OLD d'un attribut de l'objet ?


oui

On doit par contre renvoyer le return OLD pour pouvoir effectuer d'autres triggers ???


non (je rectifie) la valeur retournée par un trigger AFTER est toujours ignorée. Donc, si vous définissez plusieurs triggers AFTER sur une table, ils seront tous exécutés à moins de lever une erreur


Jean-Marie
Azimut

Hors ligne

 

#9 Fri 08 January 2021 09:43

tweaxy
Participant actif
Lieu: Abbeville
Date d'inscription: 27 Dec 2018
Messages: 76

Re: Trigger suppression d'objets dans une table tierce

Bonjour,

Je vous remercie pour ces précisions.

Cordialement,
Léandre

Hors ligne

 

Pied de page des forums

Powered by FluxBB