#1 Wed 30 May 2018 15:54
- bruhnild
- Participant actif
- Lieu: Lyon
- Date d'inscription: 7 Jun 2014
- Messages: 130
Trigger - mise à jour de champs avec une séquence
Bonjour,
Je travaille actuellement sur la constitution d'une table adresse (t_adresse) au format gracethd.
Afin de faciliter le remplissage de la table, je crée des triggers qui viendront mettre à jour une partie de ses attributs au fur et à mesure de l'ajout de points d'adresses.
Pour commencer j'ai créé une séquence d'incrémentation pour le champs ad_code (id de t_adresse)
Code:
DROP SEQUENCE IF EXISTS ban.t_adresse_incrementation_ad_code; CREATE SEQUENCE ban.t_adresse_incrementation_ad_code INCREMENT 1 MINVALUE 000000000 MAXVALUE 999999999 START 1 CACHE 1; ALTER TABLE rbal.t_adresse OWNER TO postgres; CREATE OR REPLACE FUNCTION nextval_special() RETURNS TEXT LANGUAGE sql AS $$ SELECT to_char(nextval('ban.t_adresse_incrementation_ad_code'), 'FM000000000'); $$;
Cette séquence a l'air de marcher puisque lorsque je fais
Code:
select concat('AD700',nextval_special()) as ad_code from rbal.t_adresse
.
J'ai ensuite écrit un trigger qui met à jour le champs "ad_code" lors de l'insertion ou de l'update d'un nouvel objet dans la table :
Code:
CREATE OR REPLACE FUNCTION update_ad_code() RETURNS TRIGGER AS $$ BEGIN NEW.ad_code := concat('AD700',nextval_special()) as ad_code ; RETURN NEW; END; $$ LANGUAGE 'plpgsql'; DROP TRIGGER IF EXISTS trg_update_ad_code ON rbal.t_adresse; CREATE TRIGGER trg_update_ad_code BEFORE INSERT OR UPDATE OF geom ON rbal.t_adresse FOR EACH ROW EXECUTE PROCEDURE update_ad_code();
Malheureusement lorsque je fais le test de rajouter une nouvelle entité depuis Qgis, j'obtiens une erreur de commit (voir screenshot en pj).
La fonction nextval_special() existe puisque je l'ai crée juste avant.. Je n'arrive pas à comprendre mon erreur. Pourriez vous m'aider?
Merci d'avance pour vos retours!
Marine.
Hors ligne
#2 Wed 30 May 2018 17:03
- bruhnild
- Participant actif
- Lieu: Lyon
- Date d'inscription: 7 Jun 2014
- Messages: 130
Re: Trigger - mise à jour de champs avec une séquence
J'ai résolu le problème de la séquence manquante, il me semble qu'au lieu de pointer vers le schéma "rbal" je pointais vers le schéma "ban".
Entre temps j'ai une deuxième erreur...j'aurai du m'y attendre:
Code:
Impossible de valider les changements pour la couche t_adresse Erreurs : ERREUR : 1 attribut non-ajouté. Erreur du fournisseur de données : Erreur PostGIS lors de l'ajout d'entité : ERREUR: la valeur d'une clé dupliquée rompt la contrainte unique « t_adresse_pk » DETAIL: La clé « (ad_code)=(AD700000000004) » existe déjà.
L'incrémentation part de 0 au lieu de partir du dernier numero ad_code soit AD700000000244.
Je voudrais que mon entité ait le numéro AD700000000245.
J'ai tenté cette syntaxe sans succès :
Code:
CREATE OR REPLACE FUNCTION nextval_special() RETURNS TEXT LANGUAGE sql AS $$ SELECT to_char(nextval('rbal.t_adresse_incrementation_ad_code',max(ad_code)), 'FM000000000'); $$;
Hors ligne
#3 Wed 30 May 2018 17:59
Re: Trigger - mise à jour de champs avec une séquence
Bonjour,
Je trouve que vous vous compliquez la vie, la fonction nextval_special() n'a pas d'intérêt.
Je ferai plutôt :
Code:
CREATE OR REPLACE FUNCTION update_ad_code() RETURNS TRIGGER AS $$ BEGIN NEW.ad_code := 'AD700' || to_char(nextval('ban.t_adresse_incrementation_ad_code'), 'FM000000000'); RETURN NEW; END; $$ LANGUAGE 'plpgsql';
Si la numérotation n'est pas correcte, il faut vérifier la dernière valeur de la séquence avec
Code:
select last_value from ban.t_adresse_incrementation_ad_code;
et la comparer à la dernière clé obtenue.
Jean-Marie
Azimut
Hors ligne
#4 Wed 30 May 2018 18:00
- tumasgiu
- Membre
- Lieu: Ajaccio
- Date d'inscription: 5 Jul 2010
- Messages: 1160
Re: Trigger - mise à jour de champs avec une séquence
Bonjour,
si j'ai compris vous souhaitez concaténer
des colonnes pour répondre à un format précis,
dans ce cas pourquoi ne pas créer une vue
qui présentera les colonnes normalisées ?
Code:
CREATE TABLE adresse ( id serial -- ,d'autre attributs ); CREATE VIEW adresse_gracethd AS ( SELECT 'AD700' || to_char(id, 'FM000000000') AS ad_code --, mes autres attributs FROM adresse );
Les triggers de mise à jour de champ sont généralement considérés
comme une mauvaise pratique dans le monde des SGBDR,
on leur préfère des champs calculés ou des vues
Dernière modification par tumasgiu (Wed 30 May 2018 18:27)
Hors ligne
#5 Mon 04 June 2018 11:18
- bruhnild
- Participant actif
- Lieu: Lyon
- Date d'inscription: 7 Jun 2014
- Messages: 130
Re: Trigger - mise à jour de champs avec une séquence
Bonjour,
Merci à tous les deux pour vos réponses.
Jmarsac, votre solution ne me permet pas d'incrémenter la séquence à partir de la dernière valeur (max) de ad_code se trouvant dans la table rbal.t_adresse.
A la place j'ai réécris la fonction comme ceci et ça tourne :
Code:
CREATE OR REPLACE FUNCTION fn_update_ad_code() RETURNS TRIGGER AS $$ BEGIN NEW.ad_code := 'AD' ||mAX(CAST(REPLACE(REPLACE(ad_code, 'AD', ''), '', '') as numeric)+1)from rbal.t_adresse; RETURN NEW; END; $$ LANGUAGE 'plpgsql';
Et voici le trigger :
Code:
DROP TRIGGER IF EXISTS trg_update_ad_code ON rbal.t_adresse; CREATE TRIGGER trg_update_ad_code BEFORE INSERT OR UPDATE OF geom ON rbal.t_adresse FOR EACH ROW EXECUTE PROCEDURE fn_update_ad_code();
Voir en PJ pour le résultat visuel de la table attributaire.
Tumasgiu, je concatène effectivement des colonnes pour créer ma séquence dans la table rbal.t_adresse mais j'ai besoin de créer une table et non une vue car celle ci sera alimentée manuellement pour certains champs par la suite.
Hors ligne
#6 Mon 04 June 2018 11:29
- tumasgiu
- Membre
- Lieu: Ajaccio
- Date d'inscription: 5 Jul 2010
- Messages: 1160
Re: Trigger - mise à jour de champs avec une séquence
Tumasgiu, je concatène effectivement des colonnes pour créer ma séquence dans la table rbal.t_adresse mais j'ai besoin de créer une table et non une vue car celle ci sera alimentée manuellement pour certains champs par la suite.
Vous pouvez très bien utiliser la table pour les modifications,
et la vue pour la consultation/export.
Mais sinon PostgreSQL possède un mécanisme qui permet d'avoir des vues "modifiables".
Concrètement, vous créez des triggers utilisant l'évènement INSTEAD OF sur votre vue,
qui redirigent les mises à jours vers la table source.
Un petit exemple :
https://vibhorkumar.blog/2011/10/28/instead-of-trigger/
Dernière modification par tumasgiu (Mon 04 June 2018 11:45)
Hors ligne