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 :

insert avec condition sur une table et trigger qui modifie cette même table


Sujet :

SQL Procédural MySQL

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 12
    Points : 11
    Points
    11
    Par défaut insert avec condition sur une table et trigger qui modifie cette même table
    Bonjour,

    J'ai un petit problème avec ce qui semble être une limitation bête et méchante de mysql (j'espère me tromper)

    Pour résumer, j'ai une table t1 où je dois faire des insert en fonction d'actions d'un utilisateur (php), mais des règles s'appliquent qui disent si je peux ou non faire un insert de tel ou tel type.
    Là où ça se complique, c'est que les règles dépendent de ce qui est déjà dans ma table t1, et une autre table t2 liste les règles. Une colonne ok de t2 permet de savoir directement si la règle permet ou non un insert dans t1.

    Actuellement j'ai donc ceci:
    - une proc stock qui recalcule la colonne ok de t2 en fonction du contenu de t1
    - un trigger qui lancer la proc stock à chaque insert/delete dans t1

    Et, comme je ne suis pas à l'abris qu'un utilisateur tente un insert interdit, je doit vérifier les règles lors de l'insert, ce qui donne

    insert into t1
    select valeurs
    from ...
    where t2.ok

    Et là MySQL me dit : Can't update table 't2' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.

    Pourtant le trigger est en "after", donc l'insert devrait déjà avoir fini le "select valeurs from ... where t2.ok" et ne plus bloquer la table t2...
    J'ai lu sur le web que quand on a cette erreur il faut passer en before mais ... la procédure stockée fait un calcul qui dépend du contenu de t1 et le but de l'invoquer à ce moment là est de prendre en compte la nouvelle ligne ... il me parait donc difficile de mettre mon trigger en "before"



    Voilà, j'espère avoir été assez clair malgré la grosse simplification que j'ai faite :-)

    Merci,

    Cordialement,

    aze555666

  2. #2
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 766
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 766
    Points : 52 561
    Points
    52 561
    Billets dans le blog
    5
    Par défaut
    MySQL ne permet pas de modifier des données de la table visée par le trigger (Oracle appelle cela une table mutante), contrairement à MS SQL Server par exemple.

    A lire sur les nombreuses limitations et la pseudo rapidité de MySQL, cet ersatz de SGBD non relationnel : http://blog.developpez.com/sqlpro/p9...udre-aux-yeux/

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 12
    Points : 11
    Points
    11
    Par défaut
    C'est pas que je ne veux pas utiliser un autre SGBD, d'autant que prendre Oracle ou SQL Server me permettrait de me limiter à l'utilisation de 2 SGBD au lieu de 3 (les 2 derniers au boulot et MySQL chez moi), ce qui serait bien évidemment plus simple d'autant que je ne suis pas spécialisé dans les BDD.

    Mais il se trouve que c'est un projet perso en php/mysql, avec un bandeau de pub dont j'espère tirer le prix de la location du serveur: aucune chance que ça me rembourse une licence Oracle (je viens de jeter un oeil ça me couterait 17511€. Même en mangeant des pâtes ça le ferait pas.

    Bref, ce que je cherche est une solution de contournement. Après tout le INSERT modifie la table T1 et la proc stock qui est appelée par le trigger modifier la table T2. L'action du insert sur T2 de même que l'action de la proc stock sur T1 de limitent à de la lecture de donnée.
    On doit donc pouvoir se débrouiller pour éviter la collision.



    Edit : j'ai lu ton article, c'est vrai que ça fait peur. Heureusement il date de 2 ans et il y a 2-3 trucs corrigés, et j'utilise innoDB qui semble avoir moins de défauts.
    Concernant l'impossibilité d'écrire certaines requêtes je n'en voudrais pas trop à mysql ... j'ai eu un problème de ce type il y a exactement 2 jours avec oracle (en gros je dois écrire un calcul par update successifs le plus performant possible avec chargement de données depuis d'autres tables, et j'ai voulu faire update a ... from a inner join b. Et on m'a dit que c'était possible seulement sur SQL Server et pas Oracle, et que je devais faire un classique update a set a.col = (select from b), donc autant de sous requêtes qie de lignes à update. Heureusement, l'expert m'a rassuré en m'expliquant que les dernières versions d'Oracle sont optimisées pour que ça ait les mêmes perfs ...)
    Par contre concernant les perfs de MySQL, quand je pense justement que je fais de mon mieux pour optimiser mon site afin d'éviter d'atteindre trop vite les limites de mon serveur, ça fait pleurer.
    Vu la masse de boulot que j'ai déjà fait avec mysql, et le fait que je ne vais pas me mettre à un nouveau (et 4e) SGBD maintenant (dans 1 semaine je passe le site en prod), je vais devoir rester sur mysql.
    Mais je note dans ma TODO list 'post release' qu'une migration vers PostgreSQL ne ferait pas de mal, surtout si la fréquentation atteint comme je l'espère un niveau assez haut pour me faire changer de serveur.


    En attendant, il faut que je fasse fonctionner ça sous mysql. Le trigger fonctionne correctement dans le cas des DELETE (c'est le plus important à cause des FK avec on delete cascade). Les INSERT étant limités à une action précise je peux me permettre de retirer le trigger et appeler la proc stock depuis php (même si c'est moins élégant ...)



    question subsidiaire : j'imagine que le fork de mysql, mariaDB, souffre des mêmes défauts que mysql ?



    re-edit : ça fonctionne très bien en déclenchant la proc depuis le php après l'insert et avec le trigger pour les delete.
    Le but du topic était de trouver une vraie solution mysql, mais je suppose d'après ton message que ça n'existe pas. Mon problème étant contourné, je met un petit "résolu".

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [CakePHP] Recherche avec condition sur une table éloigné du controlleur courant
    Par Spartacusply dans le forum Bibliothèques et frameworks
    Réponses: 0
    Dernier message: 04/06/2013, 22h26
  2. Export d'une table avec condition sur une autre
    Par Hobbi1 dans le forum Import/Export
    Réponses: 2
    Dernier message: 25/03/2010, 14h35
  3. Réponses: 0
    Dernier message: 05/02/2008, 10h09
  4. Requete avec condition sur une partie de l'affichage
    Par dinver78 dans le forum Langage SQL
    Réponses: 2
    Dernier message: 06/07/2007, 09h19
  5. INSERT avec condition d'une table à une autre
    Par papipasto dans le forum Langage SQL
    Réponses: 2
    Dernier message: 28/03/2006, 13h51

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