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 :

Problème FK BDD


Sujet :

Requêtes MySQL

  1. #1
    Candidat au Club
    Femme Profil pro
    créateur d'entreprise
    Inscrit en
    Avril 2017
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : créateur d'entreprise

    Informations forums :
    Inscription : Avril 2017
    Messages : 6
    Points : 2
    Points
    2
    Par défaut Problème FK BDD
    Bonjour,

    Après avoir cherché dans de nombreuses discussions, je me permets d'exposer mon problème.
    J'ai réalisé via MySQLWorkbench une BDD. Lors de l'export sur phpmyadmin, toutes les requêtes sont bonnes, incluant les clés primaires et clés étrangères.

    Cependant sur ma table 'ligne_commande' les relations sont bien prises en compte, voici la requête : l'objectif étant qu'une ligne de commande renvoie à un id produit, de la table Produit.

    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 IF NOT EXISTS `caddie`.`ligne_commande` (
      `idligne_commande` INT NOT NULL AUTO_INCREMENT,
      `quantite` VARCHAR(45) NOT NULL,
      `session_id` VARCHAR(45) NOT NULL,
      `products_id` INT NOT NULL,
      PRIMARY KEY (`idligne_commande`, `session_id`, `products_id`),
      INDEX `fk_ligne_commande_products1_idx` (`products_id` ASC),
      CONSTRAINT `fk_ligne_commande_products1`
        FOREIGN KEY (`products_id`)
        REFERENCES `caddie`.`products` (`id`)
        ON DELETE NO ACTION
        ON UPDATE NO ACTION)
    ENGINE = InnoDB;
    Or, j'ai réalisée la même requête pour la table Panierclient, qui doit renvoyer à l' idligne_commande mais celle-ci ne fonctionne pas. Voici la seconde requête :

    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
    -- Table `caddie`.`panierclient`
    -- -----------------------------------------------------
    CREATE TABLE IF NOT EXISTS `caddie`.`panierclient` (
      `idpanier` INT NOT NULL AUTO_INCREMENT,
      `datepanier` DATETIME NOT NULL,
      `prix_total_panier` FLOAT NOT NULL,
      `quantite` INT NOT NULL,
      `poids_total` VARCHAR(45) NOT NULL,
      `idproduit_respectif` VARCHAR(45) NOT NULL,
      `quantite_respective` VARCHAR(45) NOT NULL,
      `ligne_commande_idligne_commande` INT NOT NULL,
      `ligne_commande_session_id` VARCHAR(45) NOT NULL,
      `ligne_commande_products_id` INT NOT NULL,
      PRIMARY KEY (`idpanier`, `ligne_commande_idligne_commande`, `ligne_commande_session_id`, `ligne_commande_products_id`),
      INDEX `fk_panierclient_ligne_commande1_idx` (`ligne_commande_idligne_commande` ASC, `ligne_commande_session_id` ASC, `ligne_commande_products_id` ASC),
      CONSTRAINT `fk_panierclient_ligne_commande1`
        FOREIGN KEY (`ligne_commande_idligne_commande` , `ligne_commande_session_id` , `ligne_commande_products_id`)
        REFERENCES `caddie`.`ligne_commande` (`idligne_commande` , `session_id` , `products_id`)
        ON DELETE NO ACTION
        ON UPDATE NO ACTION)
    ENGINE = InnoDB;

    Malgré des heures à chercher, je n'arrive pas à trouver mon erreur et à la modifier.
    Un regard extérieur me serait précieux.
    Merci à vous.

  2. #2
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 080
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 080
    Points : 30 790
    Points
    30 790
    Par défaut
    Citation Envoyé par abertzale64 Voir le message
    (...) mais celle-ci ne fonctionne pas. (...)
    Que signifie "ne fonctionne pas" ?

    • Une erreur de syntaxe en créant la table à partir de cette requête ? Laquelle ?
    • Tout ajout de ligne est refusé ? Avec quel message ?
    • Toutes les lignes sont acceptées, sans vérification de la contrainte ?
    • Certaines lignes sont acceptées / refusées, sans raison explicable ?
    Modérateur Langage SQL
    Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
    N'oubliez pas le bouton et pensez aux balises
    [code]
    Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
    Aide-toi et le forum t'aidera : Un problème exposé sans mentionner les tentatives de résolution infructueuses peut laisser supposer que le posteur attend qu'on fasse son travail à sa place... et ne donne pas envie d'y répondre.

  3. #3
    Candidat au Club
    Femme Profil pro
    créateur d'entreprise
    Inscrit en
    Avril 2017
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : créateur d'entreprise

    Informations forums :
    Inscription : Avril 2017
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    Dans la table 'panierclient' les entrées sont acceptées, mais chaque entrée devrait renvoyer à un `ligne_commande_idligne_commande` de la table ligne_commande.

    Or celle-ci reste à 0 malgré la présence de clé étrangère reliant les tables 'panierclient' et 'ligne_commande'.

    En essayant de supprimer les contraintes de clé étrangères puis de les recréer dans la table voici le message d'erreur.
    FK2.pdf

  4. #4
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 378
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 378
    Points : 19 054
    Points
    19 054
    Par défaut
    Salut à tous.

    Vous n'avez pas compris comme fonctionne les clefs étrangères (foreign key).
    L'erreur que vous obtenez est que vous ne respectez pas l'ordre d'insertion de votre clef étrangère !

    Vous avez deux tables, dont l'une est la table mère et l'autre la table fille.
    Dans la table fille, vous créez une clef étrangère qui va pointer sur la table mère. Par exemple :
    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
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    --------------
    SET AUTOCOMMIT = 0
    --------------
     
    --------------
    START TRANSACTION
    --------------
     
    --------------
    DROP DATABASE IF EXISTS `base`
    --------------
     
    --------------
    CREATE DATABASE `base`
            DEFAULT CHARACTER SET `latin1`
            DEFAULT COLLATE       `latin1_general_ci`
    --------------
     
    --------------
    drop table if exists `mere`
    --------------
     
    --------------
    CREATE TABLE `mere`
    ( `id`      integer unsigned  NOT NULL AUTO_INCREMENT primary key,
      `divers`  varchar(255)      NOT NULL
    ) ENGINE=InnoDB
      DEFAULT CHARSET=`latin1` COLLATE=`latin1_general_ci`
      ROW_FORMAT=COMPRESSED
    --------------
     
    --------------
    drop table if exists `fille`
    --------------
     
    --------------
    CREATE TABLE `fille`
    ( `id`       integer unsigned  NOT NULL AUTO_INCREMENT primary key,
      `libelle`  varchar(255)      NOT NULL,
      `clef`     integer unsigned  NOT NULL,
      constraint `fk_fille`  foreign key (`clef`) references `mere` (`id`) on delete no action on update no action
    ) ENGINE=InnoDB
      DEFAULT CHARSET=`latin1` COLLATE=`latin1_general_ci`
      ROW_FORMAT=COMPRESSED
    --------------
     
    --------------
    insert into `fille` (`clef`,`libelle`) values  (25, 'vingt_cinq')
    --------------
     
    ERROR 1452 (23000) at line 48: Cannot add or update a child row: a foreign key constraint fails (`base`.`fille`, CONSTRAINT `fk_fille` FOREIGN KEY (`clef`) REFERENCES `mere` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION)
    --------------
    select * from fille
    --------------
     
    --------------
    insert into `mere` (`divers`) values ('un'),('deux'),('trois')
    --------------
     
    --------------
    select * from mere
    --------------
     
    +----+--------+
    | id | divers |
    +----+--------+
    |  1 | un     |
    |  2 | deux   |
    |  3 | trois  |
    +----+--------+
    --------------
    insert into `fille` (`clef`,`libelle`) values
      (1, 'one'),
      (1, 'eins'),
      (2, 'two'),
      (2, 'zwei')
    --------------
     
    --------------
    select * from fille
    --------------
     
    +----+---------+------+
    | id | libelle | clef |
    +----+---------+------+
    |  2 | one     |    1 |
    |  3 | eins    |    1 |
    |  4 | two     |    2 |
    |  5 | zwei    |    2 |
    +----+---------+------+
    --------------
    COMMIT
    --------------
     
    --------------
    SET AUTOCOMMIT = 1
    --------------
     
    Appuyez sur une touche pour continuer...
    Comment fonctionne les clef étrangères ?
    Si vous insérez dans la table fille une clef étrangère qui n'existe pas dans la table mère, vous avez une erreur 1452.
    C'est l'erreur que vous avez dans la pièce jointe pdf.
    Elle stipule que l'insertion a été rejeté car la clef étrangère n'existe pas dans la table mère.
    Pour remédier à cela, vous devez insérer en premier la ligne dans votre table mère, et en second la ligne dans la table fille qui va faire référence à celle de la table mère.
    Sans cela, vous avez une violation de la contrainte formulée par la clef étrangère.

    Par la suite j'insère dans la table mère, les lignes 1, 2 et 3.
    Quand dans la table fille, je viens insérer des lignes faisant références à la clef primaire de la table mère, je n'ai aucun rejet.

    Remarques :

    Pour la table "ligne_commande" :

    1) vous utilisez l'auto_increment" sur la colonne `idligne_commande`.
    Pourquoi créez une clef primaire avec les colonnes `idligne_commande`, `session_id` et `products_id` ?
    La colonne `idligne_commande` suffit largement à rendre la ligne unique dans votre table.

    2) il y a une erreur dans la déclarative :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    `quantite` VARCHAR(45) NOT NULL,
    une quantité est toujours une colonne de type numérique. Pourquoi la définir en tant que chaine de caractères ?

    3) pourquoi mettre "no action" dans la définition de la clef étrangère ?
    Si par exemple, vous venez modifier ou encore supprimer la clef primaire dans votre table mère, il n'y aura aucun repercussion dans la table fille.
    Et donc, vou allez vous retrouver avec un problème d'intégrité entre vos deux tables.
    C'est peut-être voulu mais cela peut poser des problèmes dans votre façon de gérer votre contrainte de type clef étrangère.

    Pour la table `panierclient` :

    4) même remarque concernant la clef primaire. Elle est trop compliquée.

    5) il y a une erreur dans la déclarative :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    `prix_total_panier` FLOAT NOT NULL,
    un prix ne se définie pas en floattant, mais en "decimal(15,2)".
    Pourquoi ? Car en flottant vous n'aurez jamais un résultat juste.

    6) un poids est de type numétrique aussi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    `poids_total` VARCHAR(45) NOT NULL,
    Pourquoi le définir en tant que chaîne de caractères ?

    7) votre clef étrangère est trop compliqué pour être efficace.
    Normalement, elle doit pointer sur la clef primaire de la table mère, qui elle-même doit être un simple incrément.

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  5. #5
    Candidat au Club
    Femme Profil pro
    créateur d'entreprise
    Inscrit en
    Avril 2017
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : créateur d'entreprise

    Informations forums :
    Inscription : Avril 2017
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    Bonjour, merci pour votre aide.
    Je vais tenter de répondre précisemment à vos remarques.


    Citation Envoyé par Artemus24 Voir le message
    Vous n'avez pas compris comme fonctionne les clefs étrangères (foreign key).
    L'erreur que vous obtenez est que vous ne respectez pas l'ordre d'insertion de votre clef étrangère !
    La 1ère table à se remplir est la table 'ligne_commande' : lorsque le client ajoute des produits au panier, les données sont injectées dans cette table.
    Ici tout fonctionne, la relation avec la table 'products' fonctionne.
    Ceci est donc la table 'mère' pour moi, qui est bien insérer en premier.

    ligne_commande.pdf
    contrainte clé étrangère.pdf

    C'est donc la table 'panierclient' qui se remplie en second : lorsque que le panier est validé, les données doivent être injectées dans la table 'panierclient'.
    Ici rien ne fonctionne. Chaque entrée dans 'panierclient' devrait correspondre à 'idligne_commande' de la table 'ligne_commande' grâce à la présence de la clé étrangère.
    Cependant, l'entrée est impossible tant que je n'enlève pas les contraintes de clé étrangère. Et bien sûr lorsque j'enlève les clés étrangères la table n'a plus d'intérêt car l'entrée dans 'panierclient' n'est pas liée à un 'idligne_commande.

    contrainte clé étrangère NOT OK.pdf
    résultat 'tablepanierclient'.pdf

    Citation Envoyé par Artemus24 Voir le message
    Pour la table "ligne_commande" :
    1) vous utilisez l'auto_increment" sur la colonne `idligne_commande`.
    Pourquoi créez une clef primaire avec les colonnes `idligne_commande`, `session_id` et `products_id` ?
    La colonne `idligne_commande` suffit largement à rendre la ligne unique dans votre table.

    Concernant 'session_id' c'est une injection provenant du site qui me permet d'identifier un visiteur par une session unique. J'ai souhaité la définir en clef primaire pour qu'il soit unique et ainsi être référencé.

    Pour 'products_id' c'est la clé étrangère qui va pointer sur la table 'products', je ne comprends pas pourquoi elle se mets en clef primaire, cela se fait automatiquement sur MySQLWorkbench, lorsque je créée les relations.


    Citation Envoyé par Artemus24 Voir le message

    Pour la table `panierclient` :

    4) même remarque concernant la clef primaire. Elle est trop compliquée.
    Même réponse, c'est quand je créée les relations via MySqlWorkbench, que les clefs étrangères se déterminent aussi comme clefs primaires.


    Merci pour vos remarques. Cdt

  6. #6
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 378
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 378
    Points : 19 054
    Points
    19 054
    Par défaut
    Salut à tous.

    Citation Envoyé par abertzale64
    La 1ère table à se remplir est la table 'ligne_commande'
    Non !
    La première table à se remplir est la table dont vous faites références en tant que clef étrangère, à savoir `caddie`.`products`.
    Quand cette table-ci sera remplie, vous pouvez maintenant insérer dans la table `caddie`.`ligne_commande`. Pourquoi ?
    Car la valeur de la colonne `products_id` de votre table `caddie`.`ligne_commande` doit être présente dans la table `caddie`.`products`.
    Sans cette condition, vous ne pouvez pas insérer une ligne et vous aurez l'erreur 1452.

    Citation Envoyé par abertzale64
    C'est donc la table 'panierclient' qui se remplie en second
    Chronologiquement parlant, c'est la troisième, après :
    --> `caddie`.`products`.
    --> `caddie`.`ligne_commande`.

    Citation Envoyé par abertzale64
    Ici rien ne fonctionne.
    Si vous respectez l'ordre des insertions, le problème devrait se résoudre de lui-même.
    Donc si cela ne fonctionne pas, soit :
    ==> il vous manque l'une des valeurs suivante :
    ----> `ligne_commande_idligne_commande`
    ----> `ligne_commande_session_id`
    ----> `ligne_commande_products_id`)
    que vous insérez dans votre table `caddie`.`panierclient` vis-à-vis de votre table `caddie`.`ligne_commande`.

    ==> vous n'insérez pas les bonnes valeurs. Par exemple un NULL ou autre chose de non renseignée.

    Si vous reprenez mon petit exemple, vous constatez que si j'insère pour la colonne clef (foreign key) la valeur 25, une erreur 1452 se produit.
    Pourquoi ? Car dans la table mère, la valeur 25 pour la colonne id n'existe pas (normal, la table est vide).

    Tandis que les valeurs 1 ou 2 que j'insère pour la colonne clef ne posent aucun problème car ils existent déjà dans la table mère.
    C'est le respect de l'ordre des insertions qui valident ou infirment la contrainte sur la clef étrangère (ici la colonne clef).

    Vous me faites un vidage de la table `caddie`.`panierclient` mais je ne voie pas comment vous la remplissez ?

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  7. #7
    Candidat au Club
    Femme Profil pro
    créateur d'entreprise
    Inscrit en
    Avril 2017
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : créateur d'entreprise

    Informations forums :
    Inscription : Avril 2017
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    Bonjour,

    Tout d'abord, merci pour votre réponse et navrée du délais de retour.



    Citation Envoyé par Artemus24 Voir le message

    Chronologiquement parlant, c'est la troisième, après :
    --> `caddie`.`products`.
    --> `caddie`.`ligne_commande`.
    Je voulais dire que la table 'ligne_commande' se remplissait bien avant 'panierclient'

    Citation Envoyé par Artemus24 Voir le message

    Si vous respectez l'ordre des insertions, le problème devrait se résoudre de lui-même.
    Donc si cela ne fonctionne pas, soit :
    ==> il vous manque l'une des valeurs suivante :
    ----> `ligne_commande_idligne_commande`
    ----> `ligne_commande_session_id`
    ----> `ligne_commande_products_id`)
    que vous insérez dans votre table `caddie`.`panierclient` vis-à-vis de votre table `caddie`.`ligne_commande`.

    ==> vous n'insérez pas les bonnes valeurs. Par exemple un NULL ou autre chose de non renseignée.

    Toutes les valeurs sont bien renseignées dans la table 'ligne_commande' avant d'être insérer dans la table 'panierclient'

    ligne_commande.pdf


    Citation Envoyé par Artemus24 Voir le message

    Vous me faites un vidage de la table `caddie`.`panierclient` mais je ne voie pas comment vous la remplissez ?
    Voici la requête qui est executée pour remplir la table 'panierclient'

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
      {
     
    $session_id = session_id();
    $prix_total_panier = $panier->total() * 1.196;
    $quantite = ($panier->count());
    $quantite_respective[] = ($_SESSION['panier'][$product->id]);
    $qte_respective = (implode(', ', $quantite_respective));
        }
        $DB->query("INSERT INTO panierclient ( session_id, datepanier, prix_total_panier, quantite, products_id, quantite_respective) VALUES ( '$session_id', NOW(), '$prix_total_panier', '$quantite', '$idproduit', '$qte_respective' ) ");
    Merci
    A+

Discussions similaires

  1. [SQL] problème update bdd
    Par ph_anrys dans le forum PHP & Base de données
    Réponses: 4
    Dernier message: 07/06/2007, 17h59
  2. Problème En BDD access
    Par mathrb dans le forum Windows Forms
    Réponses: 1
    Dernier message: 14/05/2007, 15h16
  3. [MySQL] Problème de bdd!
    Par cyberdevelopment dans le forum PHP & Base de données
    Réponses: 8
    Dernier message: 03/04/2007, 15h00
  4. [MySQL] Problème formulaire --> bdd
    Par elmago dans le forum PHP & Base de données
    Réponses: 12
    Dernier message: 19/03/2007, 17h53
  5. [MySQL] Problème de BDD chez Free
    Par linkman dans le forum PHP & Base de données
    Réponses: 7
    Dernier message: 30/07/2006, 19h00

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