IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PostgreSQL Discussion :

Problème de trigger


Sujet :

PostgreSQL

  1. #1
    Membre à l'essai
    Homme Profil pro
    Apprenti Ingénieur R&D
    Inscrit en
    Octobre 2013
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Apprenti Ingénieur R&D
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2013
    Messages : 20
    Points : 13
    Points
    13
    Par défaut Problème de trigger
    Bonjour à tous,

    Je suis à la recherche d'un coup de main pour deux triggers.
    Le projet que je réalise est une todolist multi utilisateurs.

    J'ai un soucis sur le trigger de mise à jour des priorités lorsque je supprime une tâche.
    Par exemple :

     id | id_utilisateur |           title           |  date_com  | date_fin | priorite 
    ----+----------------+---------------------------+------------+----------+----------
      1 |              2 | prevenir salome           | 2013-12-03 |          |        1
      2 |              2 | reviser ds ego            | 2013-12-03 |          |        2
      3 |              2 | faire les course          | 2013-12-03 |          |        3
      4 |              2 | mettre le reveil          | 2013-12-03 |          |        4
      5 |              1 | nourrir le chien          | 2013-12-03 |          |        1
      6 |              1 | tester algo des priorites | 2013-12-03 |          |        2
      7 |              1 | avancer le projet         | 2013-12-03 |          |        3
      8 |              1 | apprendre rails           | 2013-12-03 |          |        4

    Lorsque je supprime, par exemple la tâche d'ID = 7, je veux que la priorité de la tache 8 (et toute les autres suivantes) diminuent de 1 pour garder une liste de priorités continues.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    DELETE FROM TODO WHERE id = 7;
    Or, en fonction de ce que je fais, soit toutes les tâches de ma table sont mise à la même prioritée, soit la tâche est supprimée mais la priorité non modifiée...

    Je dois effectuer ce traitement via un trigger en PL/pgSQL (c'est un projet dans le cadre de mon DUT Informatique).

    C'est la fonction actualise_priorite_suppresion() qui déconne, mais je n'arrive pas trop à voir pourquoi...
    Pouvez vous m'aider ?

    Merci par avance.

    Mon code source :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
     
    CREATE TABLE utilisateur (
           id SERIAL,
           login varchar(30) not null,
           password varchar(30) not null,
     
           CONSTRAINT utilisateur_pk PRIMARY KEY(id)
    );
     
     
    CREATE TABLE todo (
         id SERIAL,
         id_utilisateur integer not null,
         title varchar(70) NOT NULL,
         date_com date not null,
         date_fin date ,
         priorite numeric(3) ,
     
         CONSTRAINT todo_pk PRIMARY KEY (id),
         CONSTRAINT todo_fk FOREIGN KEY (id_utilisateur) REFERENCES utilisateur(id)
    );
     
     
    CREATE OR REPLACE FUNCTION genere_priorite() RETURNS TRIGGER AS $$
    DECLARE 
    	minprio integer;
    	maxprio integer;
    	prio integer;
    BEGIN
    	select min(priorite) into minprio from todo where id_utilisateur = new.id_utilisateur;
    	select max(priorite) into maxprio from todo where id_utilisateur = new.id_utilisateur;
    	IF minprio is null then
    	   prio = 1;
    	ELSE
    	   prio = maxprio + 1;
    	END IF;
    	new.priorite := prio;
    return new;	    
    END;
    $$
    LANGUAGE 'plpgsql' ;
     
    CREATE TRIGGER generation_priorite
    BEFORE INSERT
    ON todo
    FOR EACH ROW	
    EXECUTE PROCEDURE genere_priorite();
     
    CREATE OR REPLACE FUNCTION actualise_priorite_suppresion() RETURNS TRIGGER AS $$
    DECLARE 
    	prio_suppr integer;
    	ligne_a_modif RECORD;
    BEGIN
    	select priorite into prio_suppr from todo where id = old.id and id_utilisateur = old.id_utilisateur;
     
    	/* BOUCLE NE MARCHE PAS */
    	FOR ligne_a_modif IN select * from todo where (priorite > prio_suppr and id_utilisateur = old.id_utilisateur) LOOP
    		/*update todo set priorite = old.priorite-1;*/
    		old.priorite := old.priorite-1;	 
    	END LOOP;   
     
    return old;
    END;
    $$
    LANGUAGE 'plpgsql' ;
     
    CREATE TRIGGER actualisation_priorite_suppresion
    BEFORE DELETE
    ON todo
    FOR EACH ROW	
    EXECUTE PROCEDURE actualise_priorite_suppresion();
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    drop trigger generation_priorite on todo;
    drop trigger actualisation_priorite_suppresion on todo;
    drop table todo cascade;
    drop table utilisateur;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    insert into utilisateur(login,password) values ('salome','5678');
    insert into utilisateur(login,password) values ('maelig','1234');
     
    insert into todo(id_utilisateur,title,date_com) VALUES(2,'prevenir salome',current_date);
    insert into todo(id_utilisateur,title,date_com) VALUES(2,'reviser ds ego',current_date);
    insert into todo(id_utilisateur,title,date_com) VALUES(2,'faire les course',current_date);
    insert into todo(id_utilisateur,title,date_com) VALUES(2,'mettre le reveil',current_date);
     
    insert into todo(id_utilisateur,title,date_com) VALUES(1,'nourrir le chien',current_date);
    insert into todo(id_utilisateur,title,date_com) VALUES(1,'tester algo des priorites',current_date);
    insert into todo(id_utilisateur,title,date_com) VALUES(1,'avancer le projet',current_date);
    insert into todo(id_utilisateur,title,date_com) VALUES(1,'apprendre rails',current_date);

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Responsable Données
    Inscrit en
    Janvier 2009
    Messages
    5 198
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Responsable Données

    Informations forums :
    Inscription : Janvier 2009
    Messages : 5 198
    Points : 12 774
    Points
    12 774
    Par défaut
    Bonjour,
    Plutôt que de faire une boucle, pourquoi ne pas lancer directement un update sur la table:
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    update todo set priorite = priorite - 1 where todo.id > old.id and todo.idutilisateur = old.idutilisateur

    Tatayo.

  3. #3
    Membre à l'essai
    Homme Profil pro
    Apprenti Ingénieur R&D
    Inscrit en
    Octobre 2013
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Apprenti Ingénieur R&D
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2013
    Messages : 20
    Points : 13
    Points
    13
    Par défaut
    Effectivement, c'est quand même bien plus simple... je n'y avais même pas pensé ! Je cherchais quelque chose de bien trop compliqué je crois lol.

    Je viens de tester, et ça marche bien, merci

    J'ai encore une partie à traiter, sur laquelle je n'ai pas encore planché :

    - Sur une tâche, je peux augmenter ou diminuer de 1 sa priorité (bouton + ou bouton - sur le site web). Je cherche donc à faire un trigger qui actualisera mes priorités dans ce cas.

    Je laisse le topic en "non résolu" et je viendrai demander de l'aide ici si je bloque !

    Encore merci

  4. #4
    Membre à l'essai
    Homme Profil pro
    Apprenti Ingénieur R&D
    Inscrit en
    Octobre 2013
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Apprenti Ingénieur R&D
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2013
    Messages : 20
    Points : 13
    Points
    13
    Par défaut
    Bonjour à tous,

    Me revoici, toujours sur le même TP.
    Mes tables n'ont pas changés, les valeurs de tests non plus.

    Je cherche maintenant à faire une fonction PLPGSQL me permettant de modifier la priorité de mes tâches.
    Je m'explique:

    Lorsque j'affiche sur mon site toute mes tâches triées par priorité, j'ai un bouton [+] et un bouton [-] qui s'affiche à côté de chacune d'elle. [+] doit augmenter de 1 la priorité de ma tache (et donc descendre de 1 la priorité de la tâche suivante (je ne peux pas avoir 2 prioritées identiques dans mon application). De même, le bouton [-] doit diminuer de 1 la priorité de ma tâches et monter de 1 la priorité de la tâches suivante.

    Pour cela, j'ai créer une colonne 'action' dans ma tâble 'todo'. Un clic sur le bouton [+] fera un update de ma table todo et mettre la colonne 'action' à 2 (valeur fixée arbitrairement). De même pour [-] qui mettras action = 1.

    Je créer donc une fonction (et un trigger AFTER UPDATE ON TODO) pour éffectuer mon traitement.

    Tout se charge bien dans PostgreSQL, je peux créer la fonction, le trigger, initaliser ma table. Malheuresement, lorsque je test manuellement un "update todo set action=2 where id=6", voici l'erreur qui m'est généré :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    postgres=# update todo set action=2 where id=6;
    ERROR:  stack depth limit exceeded
    HINT:  Increase the configuration parameter "max_stack_depth" (currently 2048kB), after ensuring the platform's stack depth limit is adequate.
    CONTEXT:  SQL statement "SELECT 1 FROM ONLY "public"."utilisateur" x WHERE "login"::pg_catalog.text OPERATOR(pg_catalog.=) $1::pg_catalog.text FOR SHARE OF x"
    SQL statement "UPDATE todo SET priorite = priorite + 1 WHERE todo.action = 2"
    PL/pgSQL function "modif_priorite" line 9 at SQL statement
    Sur une bonne centaine de lignes.

    Voici le code que je propose :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    CREATE OR REPLACE FUNCTION modif_priorite() RETURNS TRIGGER AS $$
    DECLARE 
    	prio INTEGER;
    	utili VARCHAR(30);
    BEGIN
    	SELECT priorite INTO prio FROM todo WHERE todo.action = 2;
    	SELECT login_utilisateur INTO utili FROM todo WHERE todo.action = 2;
     
    	UPDATE todo SET priorite = priorite + 1 WHERE todo.action = 2;
    	UPDATE todo SET priorite = prio WHERE todo.login_utilisateur = utili AND todo.priorite = (prio+1);
     
    	UPDATE todo SET action = null WHERE action = 2;
    END;
    $$
    LANGUAGE 'plpgsql' ;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    CREATE TRIGGER modification_priorite
    AFTER UPDATE
    ON todo
    FOR EACH ROW	
    EXECUTE PROCEDURE modif_priorite();
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    CREATE TABLE todo (
         login_utilisateur varchar(30) NOT NULL,
         title varchar(70) NOT NULL,
         date_com date NOT NULL DEFAULT current_date,
         date_fin date NOT NULL DEFAULT current_date,
         priorite numeric(3) NOT NULL,
         action integer,
         id SERIAL NOT NULL,
     
         CONSTRAINT todo_pk PRIMARY KEY (id),
         CONSTRAINT todo_fk FOREIGN KEY (login_utilisateur) REFERENCES utilisateur(login),
         CONSTRAINT date_check CHECK (date_fin >= date_com)
    );
    Le code ne gère pour le moment que le cas du bouton [+]. Le cas pour le [-] étant pratiquement identique, je devrai pouvoir l'adapter rapidement après avoir résolu le soucis présenté précédement.

    Petite précision, une fois que j'ai fais la modification de ma priorité, je veux que ma colonne 'action' se remette automatiquement à NULL.
    J'espère que vous pourrez m'aider !

    Cordialement,
    Hiveship

  5. #5
    Membre expert
    Avatar de alassanediakite
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2006
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Mali

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2006
    Messages : 1 599
    Points : 3 590
    Points
    3 590
    Billets dans le blog
    8
    Par défaut
    Salut
    Une mise à jour lance un trigger qui fait une mise à jour qui à son tour lance un trigger...
    S'il n'y a pas de point d'arrêt alors...stack depth LIMIT exceeded
    @+
    Le monde est trop bien programmé pour être l’œuvre du hasard…
    Mon produit pour la gestion d'école: www.logicoles.com

Discussions similaires

  1. PL/SQL problème sur Trigger
    Par kitsune dans le forum PL/SQL
    Réponses: 4
    Dernier message: 06/12/2005, 20h35
  2. [9i] problème avec trigger after logon
    Par Michael# dans le forum Oracle
    Réponses: 2
    Dernier message: 17/03/2005, 12h14
  3. [Interbase6] Problème de triggers
    Par emeraudes dans le forum Bases de données
    Réponses: 4
    Dernier message: 08/03/2005, 09h52
  4. [SQLPLUS] - Problème de Triggers Java
    Par farcis dans le forum Oracle
    Réponses: 7
    Dernier message: 23/12/2004, 09h21
  5. [PL/SQL] problème de trigger
    Par Chuck67 dans le forum Oracle
    Réponses: 14
    Dernier message: 09/12/2004, 23h17

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo