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 :

Ajouter clé étrangère à table non vide sans erreur 1452?


Sujet :

SQL Procédural MySQL

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    75
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Décembre 2005
    Messages : 75
    Points : 44
    Points
    44
    Par défaut Ajouter clé étrangère à table non vide sans erreur 1452?
    Bonjour,

    Comment ajouter une clé étrangère sur une colonne d'une table "parent" (ou "mère" ;o) qui ferait référence à la clé primaire d'une table "enfant" (ou "fille" ;o) mais alors que la table "parent" n'est pas vide?

    Exemple,

    J'ai une table "enfant"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    CREATE TABLE `categorie` (
      `id` int(11) NOT NULL auto_increment,
      `label` varchar(255) collate utf8_unicode_ci NOT NULL
      PRIMARY KEY  (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;
    puis une table "parent"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    CREATE TABLE `objets` (
      `id` int(11) NOT NULL auto_increment,
      `categorieId` int(11) NOT NULL
      `titreFr` varchar(255) collate utf8_unicode_ci NOT NULL,
      `titreEn` varchar(255) collate utf8_unicode_ci default NULL
      `descriptionFr` text collate utf8_unicode_ci,
      `descriptionEn` text collate utf8_unicode_ci
      PRIMARY KEY  (`id`),
      KEY `categorieId` (`categorieId`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=230 ;
    C'est donc cette deuxième table qui n'est pas vide.

    OK, je peux copier ma table `objets` (structure et données) puis la vider et puis ce sera possible d'ajouter la relation via un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ALTER TABLE `objets` ADD FOREIGN KEY ( `categorieId` ) 
    REFERENCES `mydatabase`.`categorie` ( `id` );
    et ceci sans obtenir une erreur 1452 de type "Cannot add or update a child row: a foreign key constraint fails..."

    Mais, ensuite, comment repeupler la table "parent" qui n'était pas vide au début?

  2. #2
    Membre confirmé Avatar de nounetmasque
    Inscrit en
    Janvier 2003
    Messages
    494
    Détails du profil
    Informations forums :
    Inscription : Janvier 2003
    Messages : 494
    Points : 570
    Points
    570
    Par défaut
    Il se peut que je n'ai rien compris... En tout cas je ne pense que ça soit possible et surtout je ne vois pas l'utilité de mettre des clés étrangères entre deux tables si tu ne renseignes pas la table mère. En effet, les clés étrangères permettent de respecter des contraintes entre les données or ta technique revient à passer outre ces contraintes...
    "Dieu reste muet, si seulement nous pouvions convaincre l'être humain d'en faire autant."

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    75
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Décembre 2005
    Messages : 75
    Points : 44
    Points
    44
    Par défaut
    J'ai dû mal m'exprimer... Posons les bases...

    Celle que j'apelle table mère c'est celui qui a la clé étangère et celle que j'apelle table fille c'est la table liée. En d'autres termes, la valeur de ma colonne clé étrangère dans la table mère = valeur de ma clé primaire dans la table fille.

    Dans mon exemple, 'objets' est la table mère et 'categorie' la table fille. La colonne 'categorie_id' de ma table mère 'objets' fait référence à la clé primaire 'id' de ma table 'categorie' fille.

    Voici l'explication de ma question...

    J'ai à la base que la table 'objets' et celle-ci n'est pas vide. Mais la colonne 'categorie_id' était à NULL jusqu'à présents pour toutes les lignes. Maintenant, j'aimerais créer ma table 'categorie' et j'aimerais créer cette relation. Impossible! Je dois d'abord vider la table et ensuite je peux créer ma relation. Mais ensuite comment repeupler ma table 'objets' sans abotenir une erreur 1452 de type "Cannot add or update a child row: a foreign key constraint fails..."?

    Merci...

  4. #4
    Rédacteur/Modérateur

    Avatar de Antoun
    Homme Profil pro
    Architecte décisionnel
    Inscrit en
    Octobre 2006
    Messages
    6 280
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte décisionnel
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2006
    Messages : 6 280
    Points : 11 736
    Points
    11 736
    Par défaut
    sur objets, enlève la déclaration de CategorieID comme NOT NULL.
    Antoun
    Expert Essbase, BO, SQL

    La bible d'Essbase, 2ème édition

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    75
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Décembre 2005
    Messages : 75
    Points : 44
    Points
    44
    Par défaut
    OK, merci!

  6. #6
    Membre chevronné
    Profil pro
    Développeur Web
    Inscrit en
    Février 2008
    Messages
    2 109
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Février 2008
    Messages : 2 109
    Points : 2 210
    Points
    2 210
    Par défaut
    Bonjour,

    Je crois que ce que tu cherches est là :
    https://blog.developpez.com/elsuket/...des_donne_2008

    J'ai déjà créé avec ça sous SSMS pour SQL Express 2008 R2, des scripts avec les instructions INSERT INTO ... pour recréer les tables, afin de créer la méthode Seed utile pour les migrations sous MVC.

    Malheureusement j'ai l'impression qu'avec SQL Express 2014 on n'a pas toutes les options, ça n'enregistre que la structure de la table. Ou alors il y a quelque chose que je n'ai pas vu ...

    Dans le menu tâches tu as aussi une commande exporter, qui te permet d'obtenir les données dans un support externe. Normalement on devrait pouvoir écrire dans un fichier texte, chez moi ça a coincé aussi, mais je l'ai obtenu sans problème dans un fichier Excel (bien qu'il y ait eu une table d'une autre base avec, enfin quand il n'y a que ça on efface la feuille ...)

    Bien sûr, avec cette méthode-ci, ça t'oblige à mettre les mains dans le cambouis après, si tu veux un script SQL.

    Ou alors tu utilises la commande d'import, dans le même menu. Celle-là je ne l'ai pas testée.

  7. #7
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    J'ose espérer que depuis 11 ans il a trouvé la solution !

    En plus, vous répondez selon Microsoft SQL Server alors que vous êtes dans le forum MySQL !

    Bref ! Déterrer les discussions n'est pas souhaité.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  8. #8
    Membre chevronné
    Profil pro
    Développeur Web
    Inscrit en
    Février 2008
    Messages
    2 109
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Février 2008
    Messages : 2 109
    Points : 2 210
    Points
    2 210
    Par défaut
    ça voudrait dire que jamais plus, personne n'aura besoin de sauvegarder une table avant de modifier sa structure ?

    Très, très étrange.

    --
    Ah oui l'erreur de plateforme, en revanche, désolé.

  9. #9
    Membre confirmé Avatar de isabelle.letrong
    Femme Profil pro
    Conseil - Consultante en systèmes d'information
    Inscrit en
    Juillet 2010
    Messages
    109
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Conseil - Consultante en systèmes d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Juillet 2010
    Messages : 109
    Points : 487
    Points
    487
    Par défaut
    Citation Envoyé par Gluups Voir le message
    ça voudrait dire que jamais plus, personne n'aura besoin de sauvegarder une table avant de modifier sa structure ?
    Je me permets une remarque, même si la discussion est fermée : c'est juste que, dans le cas présent, cela ne servait à rien de sauvegarder la table pour la recharger après, puisque le problème était la clause NOT NULL concernant la colonne 'objets.categorieID' qui empêchait l'opération. L'opération de rechargement de la table objets après avoir ajouter la colonne objets.categorieID, aurait de toutes les manières échoué !

    Un petit retour sur la conception de cette évolution :

    Hypothèse N°1 : vous connaissez la catégorie de chacun des objets et vous souhaitez qu'à terme objets.categorieID ait l'attribut NOT NULL

    Après avoir fait l'upload de la nouvelle table 'categorie' (au passage je vous conseille de mettre les noms de table soit tous au pluriel soit tous au singulier), vous ajoutez la colonne objets.categorieID (DEFAULT NULL), puis un magnifique UPDATE ensembliste permettra de mettre à jour cette colonne. Vous pourrez alors passer l'attribut de la colonne en 'NOT NULL'.

    Hypothèse N°2 : vous ne connaissez pas la categorie de chacun des objets et objets.categorieID ne pourra manifestement pas avoir l'attribut NOT NULL

    Dans ce cas, le bon réflexe est de ne pas créer de nouvelle colonne dans 'objets' mais de créer une troisième table 'objets_categories' comprenant 2 colonnes respectivement foreign key de 'categories' et 'objets' et dont la clé primaire est constituée par ces 2 colonnes.
    Si dans un souci de simplicité apparente vous vous contentez d'ajouter une colonne objets.categorieID dans objets avec l'attribut 'DEFAULT NULL', vous devrez vous encombrer pour toujours de la gestion du NULL concernant cette colonne (oui, rappelons-nous que NULL n'est pas une valeur avec toutes les conséquences qui s'en suivent sur l'approche ensembliste...)

  10. #10
    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.

    Détérer un sujet vient de 11 ans (19/08/2007) n'a aucun intérêt !

    Citation Envoyé par gb-ch
    Comment ajouter une clé étrangère sur une colonne d'une table "parent" (ou "mère" ;o) qui ferait référence à la clé primaire d'une table "enfant" (ou "fille" ;o) mais alors que la table "parent" n'est pas vide?
    Il y a une inversion entre la notion de table mère et de table fille dans ces explications.

    C'est la table fille qui possède la clef étrangère, et cette clef étrangère va pointer sur la table mère qui possède une clef primaire.
    De plus, pour que la déclarative de la clef étrangère fonctionne, il faut que les deux types soient identiques.

    Pour la table mère (categorie) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    `id` int(11) NOT NULL auto_increment,
    pour la table fille (objets) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    `categorieId` int(11) NOT NULL
    Et voici la déclarative à mettre dans la table fille (objets) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    alter table `objets` add
      CONSTRAINT `FK_CATEGORIE` FOREIGN KEY (`categorieId`) REFERENCES `categorie` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
    Où se trouve le problème ?
    Citation Envoyé par gb_ch
    mais alors que la table "parent" n'est pas vide?
    Comme gb_ch a inversé la notion des tables mère et de fille, la table fille (objets) n'est pas vide.

    Comme le dit Isabelle letrong, nous avons deux cas.
    Sauf que je ne présente pas ses deux cas de la même façon qu'elle :
    (1)--> toutes les catégories présentes dans la table fille sont aussi présentes dans la table mère.
    (2)--> toutes les catégories présentes dans la table fille ne sont pas présentes dans la table mère.

    En fait, je vois un trois cas, qui est :
    (3)--> dans la table fille, la clef étrangère a été marqué à null pour certaine ligne.

    La réponse d'Antoun :
    Citation Envoyé par Antoun
    sur objets, enlève la déclaration de CategorieID comme NOT NULL.
    concerne justement le troisième cas.

    D'où ma question : "pourquoi la clef étrangère pour certaines lignes à été marqué à NULL ?"
    Ceci est contestable, mais comme ce choix a été fait, on ne va pas revenir dessus.

    La bonne façon de faire est le cas (1). Pourquoi ?
    Parce qu'il n'y a aucun intérêt à utiliser une clef étrangère, c'est-à-dire rattacher une ligne fille à une ligne mère si le lien ne se fait pas (à NULL).
    C'est un problème d'intégrité des données, qui est dû à un problème dans la modélisation des données.

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

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

Discussions similaires

  1. [Débutant] Requete ne retournant rien, mais table non vide.
    Par Error407 dans le forum Linq
    Réponses: 4
    Dernier message: 21/01/2014, 17h54
  2. Alerte sur table non vide
    Par Trady dans le forum MS SQL Server
    Réponses: 7
    Dernier message: 13/12/2013, 16h02
  3. [AC-2003] Table MSysAccessStorage vidée par erreur
    Par sl.info dans le forum Access
    Réponses: 5
    Dernier message: 20/02/2012, 20h11
  4. Réponses: 4
    Dernier message: 05/08/2011, 17h19

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