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

SQL Procédural MySQL Discussion :

Trigger pour recalcul de positionnement


Sujet :

SQL Procédural MySQL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Candidat au Club
    Inscrit en
    Mars 2009
    Messages
    3
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 3
    Par défaut Trigger pour recalcul de positionnement
    Version Mysql : 5.0.41

    Bonjour à tous,
    je débute avec les trigger, et je suis confrontée à un problème pour lequel je souhaite avoir votre avis.

    Dans le cadre du développement d'un CMS, j'ai besoin de pouvoir gérer le positionnement d'objets au sein d'une liste, problème classique pour les CMS.
    Par exemple, pouvoir ordonner des liens au sein de catégories, ou des images au sein d'un album, etc...

    En découvrant les trigger, je me suis dit qu'une bonne partie de la tâche avait tout intérêt à être exécutée par le sgbd, pour simplifier l'application php, et pour garantir l'intégrité des données.

    Bref, je me demande si cela est possible avec les versions de mysql actuelles.

    Voici ci-dessous l'exemple sur lequel je travaille, et pour lequel j'obtiens une
    erreur 1442 (- Can't update table 'ekw_menu_section' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.)
    Cas d'application : table menu_section, avec colonne position


    Mon trigger, ci-dessous, a pour but de mettre à jour l'ensemble des positions des objets de la table à l'insertion d'un nouvel enregistrement. Je n'ai pas encore bien peaufiner les règles de calcul, donc il y a peut-être des erreurs, mais ce n'est pas ce qui m'importe pour le moment. Car avant d'aller + loin, je voudrais m'assurer que ce que je souhaite est réalisable.


    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
    DELIMITER //
    CREATE TRIGGER ekw_menu_section_created BEFORE INSERT  ON ekw_menu_section
    FOR EACH ROW
     
    BEGIN
    DECLARE done int default 0;
    DECLARE pos,id int;
    DECLARE curpos CURSOR FOR SELECT section_id, position FROM ekw_menu_section WHERE afficher=1 AND menu_id=NEW.menu_id ORDER BY position;
    DECLARE continue HANDLER FOR NOT FOUND SET done = 1;
    SET @cpt = 1;
    OPEN curpos;
    REPEAT
    FETCH curpos INTO id, pos;
    if @cpt != NEW.position
    then
    if @cpt != pos then
    UPDATE ekw_menu_section SET position=@cpt WHERE section_id=id;
    end if;
    end if;
    set @cpt = @cpt + 1;
    UNTIL done END REPEAT;
    CLOSE curpos;
    END//
     
    DELIMITER ;

    Le trigger est créé sans erreur, mais j'ai une erreur mysql 1442 lorsque je veux insérer un nouvel enregistrement.

    Visiblement, le problème est que mysql interdit au trigger de faire un update sur la table concernée. (j'ai vérifié avec un trigger simplifié, exécutant simplement un update sur ma table, et j'ai le même pb).
    Je suppose que c'est en relation avec ce qui est dit sur le site officiel :
    http://dev.mysql.com/doc/refman/5.0/...-triggers.html

    Il y a aussi des limitations dans ce qui peut apparaître dans la commande que le déclencheur peut éxecuter lorsqu'il est activé :

    * Le déclencheur ne peut pas faire référence directe aux tables par leur nom, y copmris la table à laquelle il est associé. Par contre, vous pouvez utiliser les mots clés OLD (ancien en anglais) et NEW (nouveau en anglais). OLD fait référence à la ligne existante avant la modification ou l'effacement. NEW faire référence à la nouvelle ligne insérée ou à la ligne modifiée.
    * Le déclencheur ne peut pas exécuter de procédures avec la commande CALL. Cela signifie que vous ne pouvez pas contourner le problèmes des noms de tables en appelant une procédure stockée qui utilise les noms de tables.

    Qu'en pensez-vous?
    Ai-je tort de vouloir traiter le positionnement d'objets avec des triggers?
    Où ai-je seulement fais une erreur quelque part et c'est possible?

    Merci de votre aide,

  2. #2
    Candidat au Club
    Inscrit en
    Mars 2009
    Messages
    3
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 3
    Par défaut
    Je viens de trouver ce post :
    http://www.developpez.net/forums/d11...ne-fonctionne/

    dans un trigger concernant une table donnée, il n'est pas possible de faire un UPDATE sur la même table.
    Cela confirme bien ce que je pensais/craignais.
    Dans mon cas, l'idée de créer une autre table pour y stocker la colonne position afin que je puisse la mettre à jour ne me paraît pas très bonne car cela compliquerait mes schémas de table et alourdirait mes requêtes select, ce qui n'est pas le but recherché (je voulais justement tout simplifier).

    De plus, il m'est apparu que je risquais d'avoir des problèmes sur le trigger "update" qui allait me créer des boucles infinies si je n'y prenais pas garde (à moins que j'arrive à m'en sortir avec des variables de session).

    Bref, je crois que je vais faire autrement, peut-être une procédure stockée que mon application appellera si jamais elle existe, sinon le bon vieux système d'une fonction qui recalcule les rangs de la table.

    Au passage, je ne trouve pas beaucoup de réflexions sur le sujet de la gestion des positionnements d'objets au sein d'une liste, sur les approches logiques et techniques pour gérer ça. Ou alors c'est que j'ai mal cherché, ou que je suis la seule que cela intéresse.

    Vous en pensez quoi ?

  3. #3
    Membre confirmé
    Profil pro
    Développeur Web
    Inscrit en
    Octobre 2006
    Messages
    66
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Octobre 2006
    Messages : 66
    Par défaut
    Bonjour stephanie,

    Je cherchais à réaliser quelque chose qui semble impossible avec des triggers (un peu comme toi en fait), quand je suis tombé sur ce sujet.

    Et comme j'avais déjà un peu bossé sur le sujet des listes ordonnées.
    Je peux ressortir un peu le fruit de mon travail.

    J'avais créé quelques fonctions qui, en peu de requêtes, permettaient de changer l'ordre d'une liste.

    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
    //X est la position d'insertion
    fonction insertion ($X, $infosElement){
        //requête de décallage des éléments au dessus de celui que j'insère
        UPDATE table
        SET position = position + 1
        WHERE position >= $X
     
        //requête d'insertion de mon élément en position X
        INSERT INTO table
        blablabla...
    }
     
    //X est la position de départ, Y la position d'arrivée
    fonction déplacement ($X, $Y, $idElement){
        //décallage des autres éléments
        if($X < $Y){
            UPDATE table
            SET position = position - 1
            WHERE position > $X
            AND position <= $Y
        }
        else if($X > $Y){
            UPDATE table
            SET position = position + 1
            WHERE position >= $Y
            AND position < $X
        }
     
        //déplacement de l'élément
        UPDATE table
        SET position = $Y
        WHERE idElement = $idElement
    }
    Je ressors tout ça vite fait de tête.
    C'est certainement encore optimisable pour le déplacement.

  4. #4
    Candidat au Club
    Inscrit en
    Mars 2009
    Messages
    3
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 3
    Par défaut
    Merci superpigeon
    j'ai traité le problème avec des requêtes bien moins élégantes que les tiennes!
    je crois que je vais réécrire mes fonctions du coup.

    sinon, mon CMS (ou plutôt "générateur d'interfaces de gestion") est basé sur le framework Zend.
    J'ai réussi à automatiser la gestion des positionnements en utilisant une fonctionnalité très pratique de ce framework. On peut en effet définir des fonctions personnalisés "postInsert", "postUpdate" par exemple pour des classes d'objets donnés, ce qui permet de pouvoir effectuer des actions automatiques avant ou après chaque insertion/update/delete. En gros, cela imite les triggers, mais avec bien + de liberté.

    Pour chaque classe d'objet, je n'ai alors plus qu'à dire si le positionnement est activé ou non, et l'application s'occupe de tout.

    Merci encore pour ton code !

Discussions similaires

  1. Réponses: 1
    Dernier message: 22/02/2006, 09h02
  2. Réponses: 1
    Dernier message: 18/02/2006, 02h45
  3. Oracle 9: Trigger pour audit trail
    Par ChrisD dans le forum Oracle
    Réponses: 7
    Dernier message: 18/01/2006, 14h28
  4. TRIGGER pour des suppression en CASCADE
    Par softflower dans le forum Développement
    Réponses: 2
    Dernier message: 12/12/2005, 14h58
  5. Trigger pour faire une table "mirroir"
    Par lgomez dans le forum Oracle
    Réponses: 8
    Dernier message: 26/10/2005, 13h12

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