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 17/02/2022 13:09:10

Lamethode
Membre

Trigger non fonctionnel Postgresql 13

Bonjour à tous,
Je viens de créer un trigger afin de mettre à jour des champs d'une table.
Le trigger est le suivant:
CREATE OR REPLACE FUNCTION test_colpl()
RETURNS trigger AS $$

BEGIN   
    UPDATE "DHCollar_Planned"
        SET "Xto"=
            CASE New."HoleID"
            WHEN "Azimuth" >=0 AND "Azimuth"<180
                THEN New."Xplanned"+New."FinalDepth"
            ELSE
                New."Xplanned"-New."FinalDepth"
            END;
            RETURN NEW;
           
    UPDATE "DHCollar_Planned"
    SET "Yto"=
            CASE New."YHoleID"
            WHEN "Azimuth" >=0 AND "Azimuth"<90 OR "Azimuth" >=270 AND "Azimuth"<359
                THEN New."Xplanned"+New."FinalDepth"
            ELSE 
                New."Xplanned"-New."FinalDepth"
            END;
            RETURN NEW;
           
END $$ LANGUAGE plpgsql;

CREATE TRIGGER SrvLine
BEFORE INSERT OR UPDATE
ON "DHCollar_Planned"   
FOR EACH ROW
EXECUTE FUNCTION test_colpl();


Besoin d'aide car lors de l'importation de données j'ai le message d'erreur suivant:

ERREUR:  l'opérateur n'existe pas : character varying = boolean
LIGNE 4 :    WHEN "Azimuth" >=0 AND "Azimuth"<180
             ^
ASTUCE : Aucun opérateur ne correspond au nom donné et aux types d'arguments.
Vous devez ajouter des conversions explicites de type.

REQUTE : UPDATE "DHCollar_Planned"
        SET "Xto"=
            CASE New."HoleID"
            WHEN "Azimuth" >=0 AND "Azimuth"<180
                THEN New."Xplanned"+New."FinalDepth"
            ELSE
                New."Xplanned"-New."FinalDepth"
            END
CONTEXTE : fonction PL/pgSQL test_colpl(), ligne 4 à instruction SQL


Je précise que tous les champs impliqués sont en doubles précision.

Merci

Dernière modification par Lamethode (17/02/2022 13:11:33)

Hors ligne

#2 17/02/2022 16:27:29

rjuju
Administrateur

Re : Trigger non fonctionnel Postgresql 13

Je ne vois pas d'explication à première vue.  Pourriez-vous créer un script qui permette de reproduire le problème de zéro ?


Mis à part ça, je ne pense pas que le code soit correct de toutes façons.  Voulez-vous vraiment mettre à jour tous les enregistrements de la table à chaque déclenchement du trigger?  Pourquoi ne pas positionner tout simplement NEW."Xto" et NEW."Yto"?  De plus, la 2ème requête ne devrait à priori pas être exécutée vu qu'il y a un return entre les 2.

Hors ligne

#3 17/02/2022 18:42:05

Lamethode
Membre

Re : Trigger non fonctionnel Postgresql 13

Oups c'est les nouveaux enregistrements que je veux mettre à jour.
J'aurais repris avec SET New."Yto"= and SET New."Xto"=
   
et  supprimer le Return New qui est entre les deux instructions Update.
Le résultat est pareille

Hors ligne

#4 17/02/2022 18:44:02

Lamethode
Membre

Re : Trigger non fonctionnel Postgresql 13

Je pense que l'erreur vient peut être

de la condition car  le message dit que le charactère varying = boolean n'existe pas.

ERREUR:  l'opérateur n'existe pas : character varying = boolean
LIGNE 4 :    WHEN "Azimuth" >=0 AND "Azimuth"<180

Que puis-je faire car la mise à jour de ces champs est soumise à condition ?

Hors ligne

#5 17/02/2022 20:32:08

dverite
Membre

Re : Trigger non fonctionnel Postgresql 13

L'erreur est normale parce que l'expression CASE est  un mix incorrect des deux formes possibles de CASE

UPDATE "DHCollar_Planned"
        SET "Xto"=
            CASE New."HoleID"
            WHEN "Azimuth" >=0 AND "Azimuth"<180
                THEN New."Xplanned"+New."FinalDepth"
            ELSE
                New."Xplanned"-New."FinalDepth"
            END;

Si on veut exprimer que si "Azimuth" >=0 AND "Azimuth"<180 alors "Xto" doit prendre la valeur New."Xplanned"+New."FinalDepth" et sinon la valeur New."Xplanned"-New."FinalDepth", alors c'est la forme CASE WHEN condition1 THEN valeur1 WHEN condition2 THEN valeur2 etc... et le New."HoleID" n'a rien à faire là.

L'autre forme possible est CASE expression WHEN valeur1 THEN autre valeur ELSE ... END qui teste les égalités entre l'expression et les valeurs successives.


Un autre problème est que dans un trigger on ne met pas à jour les champs avec un nouvel UPDATE de la table qui est train d'être modifiée mais avec une assignation directe des champs: NEW.colonne := valeur;

Apparemment les champs à mettre à jour sont NEW."Xto" et NEW."Yto", mais la présence de New."HoleID" et New."YHoleID" dans ce code n'a pas de raison apparente.


Si vous avez besoin de plus d'aide sur ce code, essayez de décrire ce qu'il doit faire.

Hors ligne

#6 18/02/2022 00:39:28

Lamethode
Membre

Re : Trigger non fonctionnel Postgresql 13

Merci Daniel.

Ma base de données connaît des mises à jour journalière.
Je veux à terme générer des polylignes en me basant sur les champs Position (X,Y), Azimut et Longueur.

Etant donné que j'ai un nouveau débutant,
j'ai décidé d'opérer en 2 étapes :
       1- Créer des champs Xto et Yto qui abriteront la position des prochains points mais des champs qui seront automatiquement calculées.
       2- Générer une géométrie ligne à partir des positions de début et de fin .

Hors ligne

#7 18/02/2022 13:50:47

dverite
Membre

Re : Trigger non fonctionnel Postgresql 13

Pour 2) je ne sais pas ce que c'est

Pour 1) la syntaxe standard serait :

BEGIN
 NEW."Xto" := CASE WHEN "Azimuth" >=0 AND "Azimuth"<180
                THEN NEW."Xplanned"+NEW."FinalDepth"
            ELSE
                NEW."Xplanned"-NEW."FinalDepth"
            END;

NEW."Yto" := CASE WHEN "Azimuth" >=0 AND "Azimuth"<90 OR "Azimuth" >=270 AND "Azimuth"<359
                THEN NEW."Xplanned"+NEW."FinalDepth"
            ELSE 
                NEW."Xplanned"-NEW."FinalDepth"
            END;

 RETURN NEW;
END

En Postgres moderne (depuis la version 12) plutôt qu'un trigger on conseillerait plutôt de déclarer des colonnes générées, par exemple:

ALTER TABLE "DHCollar_Planned" ADD "YTo" numeric generated always
   as (CASE WHEN "Azimuth" >=0 AND "Azimuth"<90 OR "Azimuth" >=270 AND "Azimuth"<359
                THEN "Xplanned"+"FinalDepth"
            ELSE                            
                "Xplanned"-"FinalDepth"
            END) 
   stored;

Hors ligne

#8 18/02/2022 14:06:00

rjuju
Administrateur

Re : Trigger non fonctionnel Postgresql 13

Pour 2) j'imagine que c'est quelque chose du genre ST_MakeLine(ST_Point(xfrom, yfrom), ST_Point(xto, yto)), mais difficile à dire sans la définition de la table.

Hors ligne

#9 18/02/2022 16:39:12

Lamethode
Membre

Re : Trigger non fonctionnel Postgresql 13

Merci bien dverite.
ça a fonctionné.

Hors ligne

#10 18/02/2022 16:40:54

Lamethode
Membre

Re : Trigger non fonctionnel Postgresql 13

rjuju oui oui c'est effectivement cela mais comme  xto et yto sont des colonnes générées, il refuse.

Je vais tenter de passer par un trigger en espérant que ça marche.

Hors ligne

Pied de page des forums