Vous n'êtes pas identifié(e).

#1 23/08/2012 17:00:47

fr2ed
Membre

[Résolu] fonction qui ne marche pas en trigger

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

#2 23/08/2012 17:07:01

Marc Cousin
Membre

Re : [Résolu] fonction qui ne marche pas en trigger

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

#3 27/08/2012 13:48:33

fr2ed
Membre

Re : [Résolu] fonction qui ne marche pas en trigger

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

#4 27/08/2012 14:21:04

rjuju
Administrateur

Re : [Résolu] fonction qui ne marche pas en trigger

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.

Hors ligne

#5 27/08/2012 14:52:17

fr2ed
Membre

Re : [Résolu] fonction qui ne marche pas en trigger

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

#6 27/08/2012 15:00:05

gleu
Administrateur

Re : [Résolu] fonction qui ne marche pas en trigger

Ç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

#7 27/08/2012 15:02:56

gleu
Administrateur

Re : [Résolu] fonction qui ne marche pas en trigger

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

#8 27/08/2012 15:34:44

fr2ed
Membre

Re : [Résolu] fonction qui ne marche pas en trigger

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

Pied de page des forums