Vous n'êtes pas identifié(e).
Pages : 1
J'ai créé la fonction suivante pour tester la boucle while :
CREATE OR REPLACE FUNCTION test_while() RETURNS void AS $BODY$
DECLARE
compteur integer := 1;
total integer := (select((select length(nom) from tcommunes where oid=19694)/2));
BEGIN
while total > compteur
loop
insert into test_audit (nom_employe,salaire) values ('fred',(select (1+compteur)));
compteur :=compteur+1;
end loop;
END
$BODY$
LANGUAGE plpgsql VOLATILE;
Cette fonction marche très bien !
Mais je souhaite la déclencher avec un trigger, donc je la modifie comme suit :
CREATE OR REPLACE FUNCTION test_while() RETURNS trigger AS $BODY$
DECLARE
compteur integer := 1;
total integer := (select((select length(nom) from tcommunes where oid=19694)/2));
BEGIN
while total > compteur
loop
insert into test_audit (nom_employe,salaire) values ('fred',(select (1+compteur)));
compteur :=compteur+1;
end loop;
END
$BODY$
LANGUAGE plpgsql VOLATILE;
je crée mon trigger pour que ma procédure se lance à la modification de ma table test :
CREATE TRIGGER trigger_audit
AFTER UPDATE ON test
EXECUTE PROCEDURE test_while();
Mais quand je modifie ma table test... rien ne se passe ! ! ! Je ne comprends vraiment pas.
Merci de votre aide...
Dernière modification par fr2ed (27/08/2012 17:33:41)
Hors ligne
Le fonction trigger devrait au moins faire un RETURN NEW. Je n'ai pas regardé le reste, mais c'est déjà un pré-requis.
Par ailleurs les oid ne sont pas recommandés dans les tables. Pas depuis au moins 5 ou 6 versions majeures au moins.
Marc.
Hors ligne
Merci pour les indications.... j'ai encore un peu de mal avec les boucles !
j'ai modifié mon script avec les return selon ce que j'ai pu comprendre :
CREATE OR REPLACE FUNCTION test_while() RETURNS trigger AS $BODY$
DECLARE
compteur integer := 1;
total integer := (select((select length(nom) from tcommunes where oid=19694)/2));
BEGIN
while total > compteur
loop
insert into test_audit (nom_employe,salaire) values ('fred',(select (1+compteur)));
RETURN NEW;
compteur :=compteur+1;
end loop;
RETURN NULL;
END
$BODY$
LANGUAGE plpgsql VOLATILE;
...mais le résultat est toujours le même : pas d'erreur mais aucune insertion dans ma table !
Question subsidiaire : quand je modifie une fonction trigger, je pars du principe que le trigger va lancer la fonction modifié donc inutile de le re-créer ! J'ai bon ??
Dernière modification par fr2ed (27/08/2012 13:57:50)
Hors ligne
Bonjour,
vu qu'il s'agit d'un trigger AFTER UPDATE, RETURN NEW ou RETURN NULL aura le même effet. Le premier return quittera le trigger, donc dans votre cas il y aura au mieux une ligne insérée. SI aucune ligne n'est insérée, peut-être que la requête initialisant la variable compteur pose problème. Si vous l'initialisez avec une valeur fixe, une ligne est-elle insérée ?
Sinon oui, il lancera la fonction avec le contenu présent au moment de l'appel.
Julien.
https://rjuju.github.io/
Hors ligne
compteur integer := 1;
total integer := 5;
--total integer := (select((select length(nom) from tcommunes where oid=19694)/2));
toujours aucune ligne insérée !!
Est-il possible de vérifier l'execution d'un trigger (log ou autres) ?
On dirait que c'est le mix loop+trigger qui le chagrine ! ? !
Ne maitrisant pas encore le sujet, j'avais fait des tests : loop sans trigger ok, trigger sans loop ok !
Depuis que j'essaie de mélanger les 2 : rien !
Hors ligne
Ça marche parfaitement pour moi une fois que je supprime le "RETURN NEW". J'ai ce code :
CREATE OR REPLACE FUNCTION public.test_while()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
DECLARE
compteur integer := 1;
total integer := 5;
BEGIN
while total > compteur
loop
insert into test_audit (nom_employe,salaire) values ('fred',(select (1+compteur)));
compteur :=compteur+1;
end loop;
RETURN NULL;
END
$function$;
Guillaume.
Hors ligne
Donc tout me laisse penser que votre requête de calcul de total ne renvoit pas ce que vous voulez. À mon avis, elle vous renvoit 0...
Guillaume.
Hors ligne
select((select length(nom) from tcommunes where oid=19694)/2)
sortie de données : 3
Toujours rien avec le code de gleu !
Je viens de refaire un test avec la fonction sans trigger : ça marche nickel avec un select test_while() ! !
J'ai peut-être un souci de paramétrage ou autre sur mon serveur postgresql 8.4 !
Je teste sur un autre serveur ......
EDIT : bon pareil sur un autre serveur identique ! !
Pris d'un doute, je vire mes tables et fonctions de tests.
Je fais un copier coller de la doc posgresql, section trigger :
CREATE TABLE emp (
nom_employe text NOT NULL,
salaire integer
);
CREATE TABLE emp_audit(
operation char(1) NOT NULL,
tampon timestamp NOT NULL,
id_utilisateur text NOT NULL,
nom_employe text NOT NULL,
salaire integer
);
CREATE OR REPLACE FUNCTION audit_employe() RETURNS TRIGGER AS $emp_audit$
BEGIN
--
-- Ajoute une ligne dans emp_audit pour refléter l'opération réalisée
-- sur emp,
-- utilise la variable spéciale TG_OP pour cette opération.
--
IF (TG_OP = 'DELETE') THEN
INSERT INTO emp_audit SELECT 'D', now(), user, OLD.*;
RETURN OLD;
ELSIF (TG_OP = 'UPDATE') THEN
INSERT INTO emp_audit SELECT 'U', now(), user, NEW.*;
RETURN NEW;
ELSIF (TG_OP = 'INSERT') THEN
INSERT INTO emp_audit SELECT 'I', now(), user, NEW.*;
RETURN NEW;
END IF;
RETURN NULL; -- le résultat est ignoré car il s'agit d'un trigger AFTER
END;
$emp_audit$ language plpgsql;
CREATE TRIGGER emp_audit
AFTER INSERT OR UPDATE OR DELETE ON emp
FOR EACH ROW EXECUTE PROCEDURE audit_employe();
J'execute, je fais un update de emp : ok le trigger marche !
je modifie rapidement l'exemple en incorporant le code de la boucle while :
CREATE OR REPLACE FUNCTION audit_employe() RETURNS TRIGGER AS $emp_audit$
DECLARE
compteur integer := 1;
-- total integer :=5;
total integer := (select((select length(nom) from tcommunes where oid=19694)/2));
BEGIN
--
-- Ajoute une ligne dans emp_audit pour refléter l'opération réalisée
-- sur emp,
-- utilise la variable spéciale TG_OP pour cette opération.
--
while total > compteur
loop
IF (TG_OP = 'DELETE') THEN
INSERT INTO emp_audit SELECT 'D', now(), user, OLD.*;
RETURN OLD;
ELSIF (TG_OP = 'UPDATE') THEN
INSERT INTO emp_audit SELECT 'U', now(), user, NEW.*;
-- RETURN NEW;
ELSIF (TG_OP = 'INSERT') THEN
INSERT INTO emp_audit SELECT 'I', now(), user, NEW.*;
-- RETURN NEW;
END IF;
compteur := compteur +1;
end loop;
RETURN NULL; -- le résultat est ignoré car il s'agit d'un trigger AFTER
END;
$emp_audit$ language plpgsql;
et là....miracle : ça marche !
Soulagé, même si je ne comprends pas pourquoi le 1er code ne marchait pas !
Surement qu'a force de faire des "drop-create-table-function" dans tout les sens, ça faisait une bouillie pas très digeste pour postgresql.
Pour information, ces tests avaient pour objectif de me permettre de réaliser un trigger qui, lors de la modification d'un champ type "commentaire", doit analyser le contenu , et en fonction de ce contenu réaliser une boucle de type select.
Voilà, merci pour votre aide qui m'a été bien utile dans la compréhension des boucles et déclencheurs.
Dernière modification par fr2ed (27/08/2012 17:34:48)
Hors ligne
Pages : 1