#1 Mon 07 December 2020 14:57
- Vincent-SIABS
- Participant actif
- Date d'inscription: 20 Sep 2016
- Messages: 57
TRIGGER avec condition
Bonjour,
Je travail à la mise en place d'un trigger permettant de "remonter" un info dans une table en se basant sur un foonction spatial et une "clause" attributaire.
Je m'explique : j'ai 2 tables stockées sous POSTGIS / POSTGRES:
- Table poste_source qui contient le nom du poste source
- Table Rsx_hta qui contient les réseaux partant du poste source.
Je souhaite faire remonter de façon automatique dans la table Rsx_hta le nom du poste_source d'où part le réseau. Avec comme critère les règles suivantes :
1 - il faut que le point et la ligne aient leurs deux géométries se touchent en leur contours extérieurs. Utilsation de la fonction ST_touches
2 - il faut que le champs nom_poste dans la table Rsx_hta soit vide ou null . Utilisation du SELECT WHERE / AND / OR
J'ai donc écrit le code suivant :
Code:
CREATE OR REPLACE FUNCTION remonte_poste_source () RETURNS "trigger" AS $$ BEGIN NEW.nom_poste= (SELECT nom FROM public.rsx_hta, public.postes_source WHERE (st_touches( public.rsx_hta.geom,public.postes_source.geom) AND nom_poste = '' ) OR (st_touches( public.rsx_hta.geom,public.postes_source.geom) AND nom_poste IS NULL )) ; RETURN NEW; END; $$ LANGUAGE 'plpgsql'VOLATILE; CREATE TRIGGER remonte_poste_source BEFORE INSERT OR UPDATE ON public.rsx_hta FOR EACH ROW EXECUTE PROCEDURE remonte_poste_source ();
Le soucis est que si je commence à tracer du Rsx qui part du poste_1 et que je passe ensuite à du réseau qui part du poste_2 le trigger me remonte toujours la valeur "poste_1" même si le réseau part du poste_2. cf photo en pièce jointe.
J'ai tracé dans l'ordre chronologique en commençant par la 6. 6 et 7 sont "justes" par contre 8 remonte poste_1 alors qu'il n'a aucune geométrie commune avec... La bonne valeur serait poste_2.
Je n'arrive pas à isoler mon erreur
Merci de votre aide.
Bonne journée.
Vincent
Dernière modification par Vincent-SIABS (Mon 07 December 2020 15:30)
Hors ligne
#2 Tue 08 December 2020 11:45
- Nicolas Ribot
- Membre
- Lieu: Toulouse
- Date d'inscription: 9 Sep 2005
- Messages: 1554
Re: TRIGGER avec condition
Bonjour,
Attention avec st_touches: à la précision près, elle peut retourner false alors que les geom se touchent.
Pour passer à travers ces pb de précision, st_dwithin(geom1, geom2, precision) marche très bien.
Ensuite, vous faites une jointure (st_touches) sur tous les éléments de la table vs l'autre table or il faut joindre l'élément courant de poste_source (NEW.geom) avec les geom de rsx_hta:
Code:
st_touches( public.rsx_hta.geom,NEW.geom)
Enfin, la clause peut etre simplifiée en
Code:
st_touches( public.rsx_hta.geom,NEW.geom) AND length(coalesce(nom_poste, '')) = 0
Nicolas
Hors ligne
#3 Tue 08 December 2020 13:32
- Vincent-SIABS
- Participant actif
- Date d'inscription: 20 Sep 2016
- Messages: 57
Re: TRIGGER avec condition
Bonjour,
Merci de votre aide.
J'ai pris en compte vos corrections et ré-ecrit le trigger comme suit :
Code:
CREATE OR REPLACE FUNCTION remonte_poste_source () RETURNS "trigger" AS $$ BEGIN NEW.nom_poste= (SELECT postes_source.nom, rsx_hta.nom_poste FROM public.rsx_hta, public.postes_source WHERE (st_touches( public.rsx_hta.geom,NEW.geom) AND length(coalesce(nom_poste, '')) = 0) ; RETURN NEW; END; $$ LANGUAGE 'plpgsql'VOLATILE; CREATE TRIGGER remonte_poste_source BEFORE INSERT OR UPDATE ON public.rsx_hta FOR EACH ROW EXECUTE PROCEDURE remonte_poste_source ();
Mais il y a un soucis. En effet on appel une table NEW qui "n'existe pas" : st_touches( public.rsx_hta.geom,NEW.geom)
Dans l'ordre chronologique les postes_source sont dessinés en premier puis ensuite je trace le rsx_hta qui en part. Donc en fait c'est la géométrie "nouvelle" de rsx_hta qui doit ressortir de la requête et non celle du postes_source non ?
Encore merci pour votre aide et piste de recherche.
Cordialement,
Hors ligne
#4 Tue 08 December 2020 13:51
- Vincent-SIABS
- Participant actif
- Date d'inscription: 20 Sep 2016
- Messages: 57
Re: TRIGGER avec condition
Après correction le trigger fonctionne.
Le code :
Code:
CREATE OR REPLACE FUNCTION remonte_poste_source () RETURNS "trigger" AS $$ BEGIN NEW.nom_poste= (SELECT p.nom FROM public.postes_source as p WHERE (st_touches( p.geom,NEW.geom) AND length(coalesce(new.nom_poste, '')) = 0) ); RETURN NEW; END; $$ LANGUAGE 'plpgsql'VOLATILE; CREATE TRIGGER remonte_poste_source BEFORE INSERT OR UPDATE ON public.rsx_hta FOR EACH ROW EXECUTE PROCEDURE remonte_poste_source ();
Encore merci pour votre aide !
Bonne journée.
Vincent
Dernière modification par Vincent-SIABS (Wed 09 December 2020 15:00)
Hors ligne
#5 Tue 08 December 2020 14:19
- Nicolas Ribot
- Membre
- Lieu: Toulouse
- Date d'inscription: 9 Sep 2005
- Messages: 1554
Re: TRIGGER avec condition
Vous pouvez faire plus direct dans le code de la fonction trigger (plus clean aussi):
La table public.rsx_hta ne doit pas etre référencée dans ce code: le trigger agit sur elle et déclenche pour chaque ligne, représentée par NEW.
Il faut juste référencer l'autre table sur laquelle vous voulez faire la requete:
Code:
NEW.nom_poste= p.nom FROM public.postes_source p WHERE (st_touches( p.geom,NEW.geom) AND length(coalesce(p.nom_poste, '')) = 0) ;
Nicolas
Hors ligne
#6 Tue 08 December 2020 14:21
- Vincent-SIABS
- Participant actif
- Date d'inscription: 20 Sep 2016
- Messages: 57
Re: TRIGGER avec condition
oups erreur dsl
Dernière modification par Vincent-SIABS (Tue 08 December 2020 14:25)
Hors ligne
#7 Tue 08 December 2020 14:25
- Vincent-SIABS
- Participant actif
- Date d'inscription: 20 Sep 2016
- Messages: 57
Re: TRIGGER avec condition
ah oui bien vu je vais m'être à jour mon post précédent.
et merci pour l'écriture plus clean ;-)
Hors ligne