Vous n'êtes pas identifié(e).
Bonjour @ tous,
Je souhaiterais modifier ma séquence (si nécessaire) via un trigger lors de l'insertion d'un objet.
Pour faire clair, je souhaiterais que la valeur actuelle de la séquence, soit équivalente à la valeur Max dans ma table. J'ai donc créé un code dasn le style :
CREATE OR REPLACE FUNCTION update_sequence()
RETURNS trigger AS
$BODY$
DECLARE max_id integer;
DECLARE seq_id integer;
BEGIN
SELECT MAX(NEW.id) FROM table INTO max_id;
SELECT last_value FROM "table_id_seq" INTO seq_id;
IF
max_id<>seq_id
THEN
SELECT setval('table_id_seq', max_id, true);
END IF;
RETURN NULL;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE
COST 100;
ALTER FUNCTION update_sequence() OWNER TO postgres;
CREATE TRIGGER update_sequence
BEFORE UPDATE
ON table
FOR EACH ROW
EXECUTE PROCEDURE update_sequence();
Mais là, ça fait FLOP...
C'est le SELECT setval que j'ai du mal à gérer depuis un trigger, étant donné qu'il veut systématiquement un RETURN...
Merci
Merci Julien pour la réponse,
Le besoin a finalement été modifié, je n'utiliserais donc pas forcément cet code là (cette fois-ci).
Pour info finalement on m'a demande de concaténer l’ensemble des résultat dans un seul champ texte ça donne quelque chose du genre :
SELECT array_to_string(array_agg(id_troncon),' / ') AS id_troncon,COUNT(*) AS nb_id_troncon INTO variable FROM
(SELECT id_troncon FROM diag_route WHERE ST_Overlaps (NEW.wkb_geometry,diag_route.wkb_geometry)=TRUE OR ST_Contains (NEW.wkb_geometry,diag_route.wkb_geometry)=TRUE);
NEW.troncon_trav=variable.id_troncon;
NEW.nb_troncon_trav=variable.nb_id_troncon;
A bientôt et merci pour votre aide!
Chaque ID de troncon doit être séparé pour pouvoir les traiter derrière. Je n'ai jamais utilisé de curseur dans un trigger je vais regarder comment faire et je reviens pour vous tenir au courant.
Et oui peut être faut-il que je mette en place un count suivit d'un LOOP?
Bonjour @ tous,
je n'ai pas trouvé la réponse à ma question dans les sujets existant, je me penche donc vers vous.
Voici le problème :
J'utilise l'extension postgis. J'essaie de mettre en place un trigger, qui :
1- J'ai une succession de troncons sur une route avec un ID/troncon (TABLE 2)
2- Je dessine une ligne à cheval sur 2/3/3/4... troncons (TABLE 1)
3- Le trigger entre en jeu, et récupére l'ID des 2/3/4... troncons et je l'intègre dans un champ idtroncon1/idtroncon2/idtroncon3/idtroncon4... (TABLE 1)
Voici mon trigger actuel :
CREATE OR REPLACE FUNCTION touches_test()
RETURNS trigger AS
$BODY$
DECLARE troncon record;
BEGIN
SELECT DISTINCT materiau_cana INTO troncon FROM test_sdf WHERE ST_Overlaps (NEW.wkb_geometry1,test_sdf.wkb_geometry)=TRUE;
NEW.modif=troncon; ----Et là, la question qui, tue, comment je récupère ce qui se trouve dans mon record???
NEW.modif2=troncon;
RETURN NEW;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE
ALTER FUNCTION touches_test() OWNER TO postgres;
Au cas ou vous auriez loupé la question caché dans le code :
Et là, la question qui, tue, comment je récupère ce qui se trouve dans mon record???
Merci d'avance!
Geo-x
D'accord, merci Marc, donc j'ai testé et voici une solution codée :
CREATE OR REPLACE FUNCTION update_modifs()
RETURNS "trigger" AS
$BODY$
BEGIN
IF
old.colonneA IS NULL OR new.colonneA IS NULL
THEN
NEW.coloneB='';
RETURN NEW;
ELSIF
new.colonneA<>old.colonneA
THEN
NEW.coloneB:='Modifié';
RETURN NEW;
END IF;
END;
$BODY$
LANGUAGE 'plpgsql'IMMUTABLE;
ALTER FUNCTION update_modifs() OWNER TO postgres;
CREATE TRIGGER update_modifs
BEFORE INSERT OR UPDATE ON table
FOR EACH ROW
EXECUTE PROCEDURE update_modifs();
A bientôt!
C'est donc ça!
De quoi s'arracher les cheveux. Il n'existe aucun moyen de contourner ce problème avec la 8.4 ?
Bonjour à tous,
ravi de vous retrouver aujourd'hui pour un nouveau problème.
J'essaie de mettre en place un trigger, qui permet de modifier une colonne B (en y intégrant le texte 'Modifié'), si une colonne A est modifiée.
Voici le code actuel :
CREATE OR REPLACE FUNCTION update_modifs()
RETURNS "trigger" AS $BODY$
BEGIN
NEW.colonneB:='Modifié';
RETURN NEW;
END;
$BODY$
LANGUAGE 'plpgsql'IMMUTABLE;
ALTER FUNCTION update_modifs() OWNER TO postgres;
CREATE TRIGGER update_modifs
BEFORE INSERT OR UPDATE OF colonneA ON table
FOR EACH ROW
EXECUTE PROCEDURE update_modifs();
Et avec toutes la doc, je ne vois pas du tout d'où peut venir le problème, il me met le message suivant :
ERROR: syntax error at or near "OF"
LIGNE 16 : AFTER INSERT OR UPDATE OF colonneA ON table
Le OF le dérange visiblement. Avez-vous une explication?
Bonjour à tous,
Finalement j'ai opté pour la solution : je met les buffer dans la même table, et le code donne ceci :
CREATE OR REPLACE FUNCTION update_buffer()
RETURNS trigger AS $BODY$
BEGIN
IF NEW.contrainte1 IS NOT NULL
THEN
NEW.buffer1=buffer(NEW.wkb_geometry,NEW.contrainte1);
END IF;
IF NEW.contrainte2 IS NOT NULL
THEN
NEW.buffer2=buffer(NEW.wkb_geometry,NEW.contrainte2);
END IF;
RETURN NEW;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
ALTER FUNCTION update_buffer() OWNER TO postgres;
CREATE TRIGGER update_buffer
BEFORE INSERT OR UPDATE
ON table
FOR EACH ROW
EXECUTE PROCEDURE update_buffer();
Bonjour tout le monde,
1- Gleu j'ai testé votre fonction et j'ai eu comme retour le même message d'erreur que la dernière fois : Record 'new' has no field 'buffer1'
2- Je pensais que le dblink servait à interroger d'autres tables (y compris dans la même BDD) donc dans ce cas préçis, ou les deux tables sont dans la même BDD il suffit que je fasse quelque chose du style :
SELECT INTO buff contrainte,wkb_geometry,buffer1
FROM table1,table2;
3-Par rapport aux géométries, quand je dis que je ne peux pas en avoir plusieurs dans la même table je dis ça puisqu'il s'agit de type de géométries différentes à savoir LINESTRING pour le réseau et POLYGON pour le buffer. Par conséquent ma table2 (réseau) est déclaré dans le geometry_columns en LINESTRING et la table 1 en POLYGON.
4-Marc, j'ai essayé de faire cette fonction sur une même talbe et ça fonctionne oui, c'est juste la liaison entre deux tables différentes que je n'arrive pas à faire...
Bonjour gleu,
J'ai testé un truc comme ça :
CREATE OR REPLACE FUNCTION update_buffer1()
RETURNS trigger AS $BODY$
DECLARE
buff RECORD;
BEGIN
SELECT INTO buff contrainte,wkb_geometry
FROM table2;
SELECT foo.geom_buffer1
FROM dblink('hostaddr=xxx.x.x.x port=xxxx dbname=name user=xxxxx password=xxxx',
'SELECT geom_buffer1 FROM table1') AS foo(geom_buffer1 geometry);
NEW.geom_buffer1=buffer(buff.wkb_geometry,buff.contrainte);
RETURN NEW;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
ALTER FUNCTION update_buffer1() OWNER TO postgres;
CREATE TRIGGER update_buffer1
BEFORE INSERT OR UPDATE
ON table2
FOR EACH ROW
EXECUTE PROCEDURE update_buffer1();
Mais toujours pas de sucés...c'est désespérant
En fait le dblink est un peu obligatoire, puisque la géométrie d'un buffer et celle d'un réseau sont différentes. Du coup j'ai une table contenant le réseau et l'autre contenant le buffer associé au réseau.
A moins qu'on puisse mettre des géométries différentes dans une même table?!
C'est exactement ce que je voulais faire frost242!
mais je ne connaissais pas du tout cette variable datestyle, qui est quand même très importante.
Tout marche niquel, merci pour l'aide et pour la petite démo ;-)
bonne journée.
Alors je vais commencer par la table qui contient des champs définis en 'timestamp without time zone'
Je fais une intégration dans ma BDD via un logiciel de SIG de dates au format 'DD/MM/YYYY'
Mais quand je tente l'intégration avec mon trigger en route, voici ce que j'obtiens :
Une erreur s'est produite :
ERROR: function to_timestamp(timestamp without time zone, unknown) does not exist
LIGNE 1 : SELECT to_timestamp( $1 ,'DD/MM/YYYY')
^
ASTUCE : No function matches the given name and argument types. You might need to add explicit type casts.
REQUÊTE : SELECT to_timestamp( $1 ,'DD/MM/YYYY')
CONTEXTE : PL/pgSQL function "update_char2date" line 3 at assignment
Bonjour Gleu,
merci pour votre piste, j'ai essayé quelque chose mai sans plus de succès :
CREATE OR REPLACE FUNCTION update_buffer1()
RETURNS trigger AS $BODY$
DECLARE
buff RECORD;
BEGIN
SELECT INTO buff foo.contrainte,foo.wkb_geometry,buffer1
FROM table1 ,dblink('hostaddr=xxx.x.x.x port=xxxx dbname=name user=xxxxx password=xxxx',
'SELECT wkb_geometry,contrainte_emprise1 FROM table2')
AS foo(wkb_geometry geometry,contraintedouble precision);
buff.buffer1=buffer(buff.wkb_geometry,buff.contrainte);
NEW.buffer1=buff.buffer1;
RETURN NEW;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
ALTER FUNCTION update_buffer1() OWNER TO postgres;
CREATE TRIGGER update_buffer1
BEFORE INSERT OR UPDATE
ON table2
FOR EACH ROW
EXECUTE PROCEDURE update_buffer1();
En message d'erreur il me met : Record 'new' has no field 'buffer1', alors j'ai essayé entre la fin de la première requête et le return new de mettre quelque chose comme ça (j'ai essayé différentes variantes):
SELECT buffer1 FROM buffer_reseau
NEW.buffer1=buff.buffer1;
Mais ça ne marche pas plus...
concernant le dblink, y a-t-il une autre alternative à moins de modifier la structure des tables?
Merci d'avance.
Et une impasse ne venant jamais seule,
je viens vers vous parce que j'essaie de mettre en place une mise à jour automatique d'un buffer (dans table1) à partir de la géométrie d'un reseau (table2)
En clair j'aimerais lors de la mise à jour et et/ou l'insertion d'un reseau, le buffer associé se mette à jour dans l'autre table.
table1 (geom_buffer1 geometry)
table2 (wkb_geometry geometry, contrainte integer)
Voici pour le moment le code que j'ai développé :
CREATE OR REPLACE FUNCTION update_buffer1()
RETURNS trigger AS $BODY$
BEGIN
SELECT foo.contrainte,foo.wkb_geometry,geom_buffer1
FROM table1 ,dblink('hostaddr=xxx.x.x.x port=xxxx dbname=name user=xxxxx password=xxxx,
'SELECT wkb_geometry,contrainte FROM table2' )
AS foo(wkb_geometry geometry,contrainte integer);
NEW.geom_buffer1=buffer(foo.wkb_geometry,foo.contrainte);
RETURN NEW;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
ALTER FUNCTION update_buffer1() OWNER TO postgres;
CREATE TRIGGER update_buffer1
BEFORE INSERT OR UPDATE
ON table2
FOR EACH ROW
EXECUTE PROCEDURE update_buffer1();
Là c'est (une fois de plus) le vide absolu après avoir essayé une dizaine de choses différentes. A chaque fois j'ai l'impression de pas être loin mais je ne trouve pas le truc qu'il manque :-(
Merci de votre aide si vous avez une idée.
Bonjour tout le monde,
cela faisait un petit bout de temps que je n'étais pas venu vous voir, mais pendant ce temps j'ai continué à développer des petits trigger, et aujourd'hui, je bloque sur un trigger qui modifierait une suite de caractères au format timestamp without time zone.
cette suite de caractères (champ_source) est constitué de la sorte ex. : 29/01/2001
Pour ça, j'ai trouvé la fonction : to_timestamp(champ_source,'DD/MM/YYYY')
qui modifie correctement le format.
L'idée ça serait évidemment qu'à l'insertion de ces caractères dans la table ils se mettent en auto au bon format.
Alors pour le moemnt j'ai développé ça :
CREATE OR REPLACE FUNCTION update_char2date()
RETURNS "trigger" AS $date$
BEGIN
NEW.date_referentiel=to_timestamp(NEW.date_referentiel,'DD/MM/YYYY');
NEW.date_acquisition=to_timestamp(NEW.date_acquisition,'DD/MM/YYYY');
RETURN NEW;
END;
$date$
LANGUAGE 'plpgsql';
ALTER FUNCTION update_char2date() OWNER TO postgres;
CREATE TRIGGER update_char2date BEFORE INSERT OR UPDATE
ON table FOR EACH ROW
EXECUTE PROCEDURE update_char2date();
Mais ça ne fonctionne pas...pourtant l'enthousiasme y était...
auriez-vous une idée pour me dépatouiller de cette problématique, ou bien il est impossible d'insérer du caractère dans une colonne définit en timestamp, donc le problème doit se résoudre en amont?!
Merci d'avance.
En effet l'update qui tourne en boucle, ça me parait beaucoup plus clair maintenant, et ça me parait tellement évident. Ca veut donc dire qu'on ne peut pas faire d'update à partir d'un trigger, si j'ai bien compris...
Par rapport au code, je ne savait pas qu'en intégrant un SELECT INTO dans un trigger, il ne crée pas en 'dur' la table dans la BDD.
J'ai réussi à adapter la requête que vous m'avez donné et je vous remercie vivement pour l'aide que vous m'avez apporté.
Bonne continuation et peut être à bientôt. ;-)
Bonjour gleu,
En fait j'aurais aimé savoir si les conditions dans une fonction qui renvoi un trigger, s'écrit de manière général de la façon dont je l'ai écrite sur mon précédent post
Je pose cette question, sachant que le trigger ne fonctionne pas correctement (j'ai l'impression qu'avec ce trigger l'update tourne en boucle dans le vide et la base plante).
Dans le même style j'ai testé de créer un trigger avec le code suivant :
Avec deux bases, une base 'commune' qui contient un code associé à une commune et une base sur laquelle je fais ma requête.
Le but étant de mettre à jour automatiquement dans ma BDD ou je fais la requête le nom de la commune en fonction du code qu'il va chercher dans la table 'commune' (Je suis clair?), ma requête qui fonctionne donne ça :
CREATE OR REPLACE FUNCTION update_e()
RETURNS "trigger" AS $BODY$
BEGIN
UPDATE e
SET e.nom=foo.nom
FROM dblink('hostaddr=127.0.0.1 port=5400 dbname=bidule user=postgres password=machin', 'SELECT code, nom FROM commune') AS foo (code integer, nom varchar)
WHERE e.code_insee=foo.code
END;
$BODY$
LANGUAGE 'plpgsql';
ALTER FUNCTION update_e()OWNER TO postgres;
CREATE TRIGGER update_eBEFORE INSERT OR UPDATE
ON eFOR EACH ROW
EXECUTE PROCEDURE update_e();
Mais quand il s'agit de la faire fonctionner on dirait que ça tourne en boucle sans s'arrêter et ça plante...
Merci de m'éclairer un peu, pour savoir si je fais un truc mal ou si j'oublie quelque chose...
Bonne journée.
Xavier
Bonjour à tous,
Voici l'idée générale de ma requête. Je souhaiterais pouvoir remplir automatiquement un champ par concaténation via un trigger.
Ce trigger appel une fonction qui met des conditions à cette mise à jour.
Voici l'idée :
CREATE OR REPLACE FUNCTION UPDATE()
RETURNS "trigger" AS $nomfic$
BEGIN
IF code_insee IS NULL THEN
NEW.nomfic:='';
ELSIF nom IS NULL
NEW.nomfic:='';
ELSIF nom AND code_insee IS NOT NULL THEN
NEW.nomfic:=NEW.code_insee||'-'||NEW.nom||'machin';
END IF;
RETURN NEW;
END;
$nomfic$
LANGUAGE 'plpgsql';
ALTER FUNCTION UPDATE()OWNER TO postgres;
CREATE TRIGGER UPDATE BEFORE INSERT OR UPDATE
ON MaTable FOR EACH ROW
EXECUTE PROCEDURE UPDATE();
En espérant que vous puissiez m'éclairer sur les conditions dans une fonction...
Merci d'avance.
Geo-x