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).

#2 PL/pgSQL » trigger update concatenation » 22/02/2024 10:38:19

Nyldan
Réponses : 2

Bonjour,

j'ai un problème sur un trigger que je perçois en partie.
Dans une table, j'ai une colonne ident avec une contrainte d'unicité. Pour créer cet ident, j'ai créée un trigger (BEFORE INSERT OR UPDATE) qui concatène 3 champs de trois autres colonnes (ident=concat(toto,'_',titi,'_',tata) : attention ce n'est pas mon code, c'est pour information).
Le problème est que quand je souhaite mettre à jour plusieurs lignes en même temps en ajoutant +1 au champ tata par exemple, j'ai un message d'erreur qui m'indique que la contrainte d'unicité est violée car un ident existe déjà. Ça me parait normal, car l'update se fait ligne par ligne et il rencontre forcément le même ident à un moment donné?

Y a t-il un moyen de contourner de celà?

Je peux détailler un peu plus avec du code par la suite si l'explication ne semble pas claire.

Merci

#3 Re : pgAdmin4 » Création table de travail parallèle » 29/03/2023 11:29:29

Bonjour,
voici ce que j'ai trouvé pour répondre à mon problème.
Après avoir copié toute les données depuis table_origine vers table_travail.
Je créée deux fonctions déclencheurs distinctes:
       - une pour les insertions et les mise à jour dans table_origine

-- FUNCTION: schema.insert_update_on_table_travail()

-- DROP FUNCTION IF EXISTS schema.insert_update_on_table_travail();

CREATE OR REPLACE FUNCTION schema.insert_update_on_table_travail()
    RETURNS trigger
    LANGUAGE 'plpgsql'
    COST 100
    VOLATILE NOT LEAKPROOF
AS $BODY$
BEGIN
IF (TG_OP = 'INSERT') THEN
INSERT INTO schema.table_travail ( value_1, value_2,...)
VALUES (new.value_1, new.value_2,…) ;
ELSEIF (TG_OP = 'UPDATE') THEN
     UPDATE schema. table_travail
     SET     value_1 = new. value_1,
                value_2 = new. value_2,
                    ....
    WHERE table_travail.identifiantunique=new.identifiantunique;
END IF;
    RETURN NEW;
END
$BODY$;

       - une pour les suppressions d'objets dans table_origine

-- FUNCTION: schema.delete_on_table_travail()

-- DROP FUNCTION IF EXISTS schema.delete_on_table_travail();

CREATE OR REPLACE FUNCTION schema.delete_on_table_travail()
    RETURNS trigger
    LANGUAGE 'plpgsql'
    COST 100
    VOLATILE NOT LEAKPROOF
AS $BODY$
BEGIN
    DELETE FROM schema.table_travail
    WHERE table_travail.identifiantunique=old.identifiantunique;
RETURN OLD;
END
$BODY$;

J'applique ces deux délclencheurs à table_origine.
un lors des insertion et des mises à jour:

CREATE TRIGGER trigger_insert_update_on_table_travail
    BEFORE INSERT OR UPDATE
    ON schema.table_origine
    FOR EACH ROW
    EXECUTE FUNCTION trigger_insert_update_on_table_travail();

un lors de la suppression:

CREATE TRIGGER trigger_maj_delete_on_table_travail
    AFTER DELETE
    ON schema.table_origine
    FOR EACH ROW
    EXECUTE FUNCTION trigger_maj_delete_on_table_travail();

A présent, dès que j'agis dans ma de table_origine, table_travail est modifiée à l'identique sur les colonnes sélectionnées dans la fonction déclencheur (toute dans mon cas) et je peux créer des colonnes dans table_travail qui n'apparaitront pas dans table_origine.
Le sujet est donc résolu pour moi, mais je ne sais pas comment le clore.

#4 Re : pgAdmin4 » Création table de travail parallèle » 15/03/2023 11:58:30

Bonjour et merci pour votre retour,

J’ai regardé un peu du côté de l’héritage mais ça ne correspond pas au besoin je pense, même si c’est très intéressant pour ma culture.

Je vais essayer de simplifier :

- table_origine  (table patrimoniale avec données géographiques (point) dans laquelle je ne souhaite pas ajouter d’autres colonnes pour le moment) =  table_travail (avec les l’ensemble des ligne de la table_origine) --> copie des données dans une autre table ok pour moi
- table_travail doit se mettre à jour à chaque évènement qui a lieu sur la table_origine (insert / update / delete) --> ???

Au gré de demandes spécifiques, je pourrai ajouter des colonnes modifiables dans table_travail et garder ma table_origine « propre ».

J’espère que c’est plus clair…

#5 Re : pgAdmin4 » Création table de travail parallèle » 14/03/2023 17:17:52

Je ne sais pas si c'est il est possible de supprimer ou déplacer ma question, mais je viens de me rendre compte qu'elle aurait certainement du être placée dans le forum Général...

#6 pgAdmin4 » Création table de travail parallèle » 14/03/2023 16:42:58

Nyldan
Réponses : 4

Bonjour à tous,

je suis relativement nouveau dans la gestion de base de donnée.

J'ai une base de données au travail (postgresql avec postgis administrée par pgAdmin 4) qui est polluée, à mon sens, à chaque demande particulière de la hiérarchie par la création d'une colonne. (Exemple de logique de mon collègue: demande --> faire remonter par nos équipes terrain toutes les poubelles de couleurs noires (donnée que nous n'avons pas) qui seront ensuite changées par des poubelles de couleur jaune / réponse--> création d'une colonne pb_noire avec oui / non en inscription) Je précise que c'est un exemple et que la colonne finira par ne plus servir.
Je ne suis pas sur que la réflexion soit idéale mais je souhaiterais créer une table "parallèle" (table_provisoire) à la table de base (table_origine) de manière à pouvoir y créer des colonnes "provisoires" et ne pas polluer l'originale. Il faudrait qu'à chaque fois qu'une entité est créée, modifiée ou supprimée dans table_origine, table_provisoire se mette à jour avec toutes les colonnes de table_origine sans condition (j'ai un identifiant unique dans ma table_origine qui s'incrémente). Peut-on passer par un trigger (que je n'arrive pas à créer...) ou autre?

J'espère que mon explication est assez claire.

Merci d'avance pour l'aide qui pourra m'être apportée!

#7 Re : Site PostgreSQL.fr » fonction et trigger concatenation » 22/04/2022 10:12:08

Bonjour,

merci beaucoup pour votre réactivité! Ça ne tenait pas à grand chose...

#8 Site PostgreSQL.fr » fonction et trigger concatenation » 22/04/2022 09:38:26

Nyldan
Réponses : 2

Bonjour,

je suis nouveau et débutant en SIG.

Je souhaiterais concaténer 3 champs (insee,'_'ar_num,'_'lum_numero) d'une table afin de mettre à jour un quatrième champ (ident) de cette même table lorsque l'un des 3 premiers champs cité est modifié.

Je travaille avec PGAdmin.

Si j'ai bien compris, je dois créer une fonction générale que je pourrais éventuellement appliquer à plusieurs tables et ensuite j'applique un trigger sur la table concernée?

J'ai récupéré un exemple que j'ai modifié mais il doit y avoir une erreur dès le départ.

Fonction:

CREATE OR REPLACE FUNCTION nom_fonction()
    RETURNS trigger
    LANGUAGE 'plpgsql'
    COST 100
    VOLATILE NOT LEAKPROOF
AS $BODY$
    BEGIN
        new.ident := concat(insee,'_',ar_numero,'_',lum_numero);
    RETURN NEW;
END

$BODY$;

Trigger:

CREATE TRIGGER test
    BEFORE INSERT OR UPDATE OF insee, ar_numero, lum_numero
    ON schema.matable
    FOR EACH ROW
    EXECUTE FUNCTION nom_fonction();

Lorsque je modifie un des trois champs dans QGIS, j'ai un message d'erreur me disant que les colonnes sélectionnées n'existent pas:

Impossible de valider les changements pour la couche geo_ep_points_lumineux_plugin

Erreurs : ERREUR : 1 modification(s) de valeurs d'attribut n'ont pas été effectuée(s).
 
Erreur du fournisseur de données :
      Erreur PostGIS lors de la modification d'attribut : ERROR:  column "insee" does not exist
    LINE 1: SELECT concat(insee,'_',ar_numero,'_',lum_numero)
                          ^
    QUERY:  SELECT concat(insee,'_',ar_numero,'_',lum_numero)
    CONTEXT:  PL/pgSQL function nom_fonction() line 3 at assignment

Lorsque je ne renvoie pas à une colonne et uniquement à du texte dans la fonction, le trigger fonctionne et mon champ se remplie avec le texte concerné.

J'espère avoir été clair, et je vous remercie par avance de votre aide.

Pied de page des forums

Propulsé par FluxBB