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

Requêtes MySQL Discussion :

Un UPDATE multi-table


Sujet :

Requêtes MySQL

  1. #1
    Expert confirmé
    Avatar de Séb.
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    5 350
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 350
    Billets dans le blog
    17
    Par défaut Un UPDATE multi-table
    Hello à tous !
    J'ai une requête UPDATE qui ne se comporte pas comme espéré.

    Description :
    - J'ai deux tables : stocks et ateliers.
    - Un atelier est rattaché à un stock, un stock peut avoir plusieurs ateliers.
    - Un stock dispose de farine, d'eau et de pain.
    - A chaque appel du UPDATE le stock doit être incrémenté de 1 pain pour 2 farine et 1 eau dispos par atelier qui lui est rattaché.

    Voici mon script de test :

    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
    DROP SCHEMA IF EXISTS boulangeries ;
    CREATE SCHEMA boulangeries ;
    USE boulangeries ;
     
    CREATE TABLE stocks (
        stock_localisation VARCHAR(30),
        stock_farine INT,
        stock_eau INT,
        stock_pain INT,
        CONSTRAINT PRIMARY KEY(stock_localisation)
    ) ;
     
    INSERT INTO stocks VALUES('Paris', 10, 6, 0),
                             ('Bordeaux', 3, 5, 1) ;
     
    CREATE TABLE ateliers (
        atelier_localisation VARCHAR(30),
        atelier_stock VARCHAR(30),
        CONSTRAINT PRIMARY KEY(atelier_localisation),
        CONSTRAINT FOREIGN KEY(atelier_stock) REFERENCES stocks(stock_localisation)
    ) ;
     
    INSERT INTO ateliers VALUES('Boulogne-Billancourt', 'Paris'),
                               ('Gradignan', 'Bordeaux'),
                               ('Nanterre', 'Paris') ;
     
    -- Affiche les ressources des ateliers
    CREATE PROCEDURE ATELIERS( )
    SELECT ALL atelier_localisation AS atelier, stock_localisation AS stock, stock_farine AS farine, stock_eau AS eau, stock_pain AS pain
    FROM ateliers INNER JOIN stocks ON atelier_stock = stock_localisation ;
     
    CREATE PROCEDURE PRODUIRE( )
    UPDATE stocks INNER JOIN ateliers ON stock_localisation = atelier_stock
    SET stock_farine = stock_farine - 2, stock_eau = stock_eau - 1, stock_pain = stock_pain + 1
    WHERE stock_farine >= 2 AND stock_eau >= 1 ;
     
    CALL ATELIERS( ) ;
    CALL PRODUIRE( ) ;
    CALL ATELIERS( ) ;
    Ce script me donne le résultat suivant :

    Avant le UPDATE :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    +----------------------+----------+--------+-----+------+
    | atelier              | stock    | farine | eau | pain |
    +----------------------+----------+--------+-----+------+
    | Gradignan            | Bordeaux |      3 |   5 |    1 |
    | Boulogne-Billancourt | Paris    |     10 |   6 |    0 |
    | Nanterre             | Paris    |     10 |   6 |    0 |
    +----------------------+----------+--------+-----+------+
    Après le UPDATE :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    +----------------------+----------+--------+-----+------+
    | atelier              | stock    | farine | eau | pain |
    +----------------------+----------+--------+-----+------+
    | Gradignan            | Bordeaux |      1 |   4 |    2 |
    | Boulogne-Billancourt | Paris    |      8 |   5 |    1 |
    | Nanterre             | Paris    |      8 |   5 |    1 |
    +----------------------+----------+--------+-----+------+
    Alors que je m'attendais plutôt à :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    +----------------------+----------+--------+-----+------+
    | atelier              | stock    | farine | eau | pain |
    +----------------------+----------+--------+-----+------+
    | Gradignan            | Bordeaux |      1 |   4 |    2 |
    | Boulogne-Billancourt | Paris    |      6 |   4 |    2 |
    | Nanterre             | Paris    |      6 |   4 |    2 |
    +----------------------+----------+--------+-----+------+
    Je dois passer à côté de qquechose, mais quoi ? Une idée ? Merci

  2. #2
    ced
    ced est déconnecté
    Rédacteur/Modérateur

    Avatar de ced
    Homme Profil pro
    Gestion de bases de données techniques
    Inscrit en
    Avril 2002
    Messages
    6 065
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Gestion de bases de données techniques
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2002
    Messages : 6 065
    Par défaut
    Bonjour,

    La requête de mise à jour a pourtant l'air correcte.
    C'est plutôt le nombre d'appels de cette requête, en fonction des stocks, qui ne fait pas ce que tu souhaites, c'est ça ? Comment cette requête est-elle appelée ?

    ced
    Rédacteur / Modérateur SGBD et R
    Mes tutoriels et la FAQ MySQL

    ----------------------------------------------------
    Pensez aux balises code et au tag
    Une réponse vous a plu ? N'hésitez pas à y mettre un
    Je ne réponds pas aux questions techniques par message privé, les forums sont là pour ça

  3. #3
    Expert confirmé
    Avatar de Séb.
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    5 350
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 350
    Billets dans le blog
    17
    Par défaut
    Salut ced !!

    Citation Envoyé par ced Voir le message
    C'est plutôt le nombre d'appels de cette requête, en fonction des stocks, qui ne fait pas ce que tu souhaites, c'est ça ?
    Là j'appelle la requête une unique fois et déjà je n'ai pas le résultat escompté.

    Comment cette requête est-elle appelée ?
    Elle est appelée depuis le script .sql collé plus haut qui me sert juste à faire qques tests sans m'encombrer de PHP. Rien d'autre pour le moment
    (j'utilise MySQL 5.1)

    J'ai l'impression que le pb vient de :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SET stock_farine = stock_farine - 2, stock_eau = stock_eau - 1, stock_pain = stock_pain + 1
    C'est comme si la précédente modification du stock_farine d'un même stock n'était pas prise en compte pour l'enregistrement suivant.

    J'illustre le fond de ma pensée...

    La jointure du UPDATE donne le jeu de résultats suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    +----------------------+----------+--------+-----+------+
    | atelier              | stock    | farine | eau | pain |
    +----------------------+----------+--------+-----+------+
    | Gradignan            | Bordeaux |      3 |   5 |    1 |
    | Boulogne-Billancourt | Paris    |     10 |   6 |    0 |
    | Nanterre             | Paris    |     10 |   6 |    0 |
    +----------------------+----------+--------+-----+------+
    Le UPDATE traite le 1er enregistrement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
      +----------------------+----------+--------+-----+------+
      | atelier              | stock    | farine | eau | pain |
      +----------------------+----------+--------+-----+------+
    =>| Gradignan            | Bordeaux |      1 |   4 |    2 |
      | Boulogne-Billancourt | Paris    |     10 |   6 |    0 |
      | Nanterre             | Paris    |     10 |   6 |    0 |
      +----------------------+----------+--------+-----+------+
    Là c'est bon. Puis traite le 2nd enregistrement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
      +----------------------+----------+--------+-----+------+
      | atelier              | stock    | farine | eau | pain |
      +----------------------+----------+--------+-----+------+
      | Gradignan            | Bordeaux |      1 |   4 |    2 |
    =>| Boulogne-Billancourt | Paris    |      8 |   5 |    1 |
      | Nanterre             | Paris    |     10 |   6 |    0 |
      +----------------------+----------+--------+-----+------+
    On voit que l'atelier de Boulogne et les stocks de Paris sont OK. Par contre l'atelier de Nanterre dont les stocks sont également à Paris ne sont pas à jour, d'où pour le traitement du 3e enregistrement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
      +----------------------+----------+--------+-----+------+
      | atelier              | stock    | farine | eau | pain |
      +----------------------+----------+--------+-----+------+
      | Gradignan            | Bordeaux |      1 |   4 |    2 |
      | Boulogne-Billancourt | Paris    |      8 |   5 |    1 |
    =>| Nanterre             | Paris    |      8 |   5 |    1 |
      +----------------------+----------+--------+-----+------+
    ... ce qui expliquerait le résultat final.

    Je m'attendais plutôt à ceci pour le 2nd UPDATE :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
      +----------------------+----------+--------+-----+------+
      | atelier              | stock    | farine | eau | pain |
      +----------------------+----------+--------+-----+------+
      | Gradignan            | Bordeaux |      1 |   4 |    2 |
    =>| Boulogne-Billancourt | Paris    |      8 |   5 |    1 |
      | Nanterre             | Paris    |      8 |   5 |    1 | (cascade)
      +----------------------+----------+--------+-----+------+
    Et donc pour le 3e :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
      +----------------------+----------+--------+-----+------+
      | atelier              | stock    | farine | eau | pain |
      +----------------------+----------+--------+-----+------+
      | Gradignan            | Bordeaux |      1 |   4 |    2 |
      | Boulogne-Billancourt | Paris    |      6 |   4 |    2 | (cascade)
    =>| Nanterre             | Paris    |      6 |   4 |    2 |
      +----------------------+----------+--------+-----+------+
    Mais non. C'est comme si les colonnes stock_* étaient rattachées à la table stocks par valeur et non pas par référence/pointeur.

    Que penses-tu de ma "théorie" ? Penses-tu que c'est un comportement normal pour MySQL ? Pour un SGBD ? Je fais peut-être fausse piste... Si tel est le cas aurais-tu une idée pour une requête équivalente ? J'aimerais éviter les procédures stockées, curseurs & cie.

  4. #4
    ced
    ced est déconnecté
    Rédacteur/Modérateur

    Avatar de ced
    Homme Profil pro
    Gestion de bases de données techniques
    Inscrit en
    Avril 2002
    Messages
    6 065
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Gestion de bases de données techniques
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2002
    Messages : 6 065
    Par défaut
    Sans être un spécialiste de la question, je pense que la mise à jour se fait comme la jointure d'une requête... Non pas ligne à ligne après jointure, mais dans chacune des tables sur les lignes concernées.
    Ainsi, l'update met à jour en une seule fois 2 lignes dans la table stocks et 3 lignes dans la table ateliers. Il ne passe pas de façon séquentielle...

    ced
    Rédacteur / Modérateur SGBD et R
    Mes tutoriels et la FAQ MySQL

    ----------------------------------------------------
    Pensez aux balises code et au tag
    Une réponse vous a plu ? N'hésitez pas à y mettre un
    Je ne réponds pas aux questions techniques par message privé, les forums sont là pour ça

  5. #5
    Expert confirmé
    Avatar de Séb.
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    5 350
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 350
    Billets dans le blog
    17
    Par défaut
    Dans ce cas comment expliquer le résultat ? La requête est pourtant simple et m'a l'air bonne non ?
    Je vais simplifier le cas au max.

  6. #6
    Expert confirmé
    Avatar de Séb.
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    5 350
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 350
    Billets dans le blog
    17
    Par défaut
    En tout cas merci pour ta participation

Discussions similaires

  1. Requête SQL Update mono ou multi table
    Par d.tellier dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 13/10/2011, 08h12
  2. UPDATE multi table
    Par cvexxx dans le forum SQL
    Réponses: 7
    Dernier message: 24/06/2011, 17h44
  3. problème update multi-tables
    Par steevest dans le forum Requêtes
    Réponses: 2
    Dernier message: 16/10/2009, 11h44
  4. update d'un champ avec select multi-table
    Par maxvador dans le forum Hibernate
    Réponses: 1
    Dernier message: 23/09/2009, 11h54
  5. UPDATE multi-tables sous SQL Server
    Par Cybernet dans le forum Langage SQL
    Réponses: 8
    Dernier message: 25/03/2004, 15h34

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