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

Langage SQL Discussion :

Deux tables avec clés étrangères entre elles


Sujet :

Langage SQL

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 11
    Points : 8
    Points
    8
    Par défaut Deux tables avec clés étrangères entre elles
    Bonjour,

    Je travaille à l'heure actuelle sur la base de données d'un site e-commerce, et je me trouve devant un petit problème.

    En effet, j'ai deux tables qui ont chacun une clé étrangère sur l'autre. Il faudrait que je puisse les déclarer en même temps (sinon la création est refusée). Ayant eu des cours sur les bases de données lors de mon cursus scolaire, je suis à peu près sûr que c'est possible, mais j'ai été incapable de trouver la réponse sur Internet :-(

    En fait, j'ai plus précisément trois tables, mais je pense que si je m'en sors avec deux, je m'en sortirais aussi avec trois ^^. Voici les tables et les contraintes voulues (je laisse juste les contraintes dedans, avec juste les parties intéressantes, mais en vrai il y a beaucoup plus d'informations) :

    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
    CREATE TABLE Clients
    (
       id INT,
     
       CONSTRAINT FOREIGN KEY (idMainAddress) REFERENCES Addresses(id),
       CONSTRAINT FOREIGN KEY (idTemporaryCart) REFERENCES Carts(id)
    );
     
    CREATE TABLE Carts
    (
       id INT,
       idClient INT,
     
       CONSTRAINT FOREIGN KEY (idClient) REFERENCES Clients(id)
    );
     
    CREATE TABLE Addresses
    (
       id INT,
       idClient INT,
     
       CONSTRAINT FOREIGN KEY (idClient) REFERENCES Clients(id)
    );
    Quelqu'un a une idée ?
    Merci d'avance !

    Naoris

    PS : je sais pas si ça peut être important, mais j'utilise MySQL

  2. #2
    Membre expérimenté
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Mayenne (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2010
    Messages : 793
    Points : 1 327
    Points
    1 327
    Par défaut
    Bonjour,

    si tu trouves une relation 1,1 des deux côtés, c'est qu'il y a une erreur de conception.
    Deux tables ne peuvent pas posséder chacune une clé étrangère vers l'autre.
    Si tu souhaites continuer ainsi, dis toi qu'un client possède 1 ou 0 adresse (à sa création tu insères d'abord le client, puis ses adresses, pire si il doit posséder une seule adresse cette table n'a aucun intérêt), de même pour la panier

  3. #3
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 801
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    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 801
    Points : 34 063
    Points
    34 063
    Billets dans le blog
    14
    Par défaut
    Il faut voir dans les clés étrangères une certaines dépendance d'une table par rapport à l'autre.

    Le client dépend-il de son adresse ou l'adresse est-elle une propriété (éventuellement multiple) du client ?
    Le client dépend-il de son panier ou le panier dépend-il du client ?

    Le fait qu'une adresse soit l'adresse principale du client est plutôt une propriété de l'adresse que du client. Tu pourrais modéliser cela par une colonne booléenne "mainAddress" dans la table des adresses.

    Idem pour le caractère temporaire d'un "cart".

    Sinon, pour répondre à ta question et dans le cas où tu aurais par exemple des cardinalités (1,1 - 1,n), la solution est dans l'écriture d'un trigger à l'insertion qui insère dans les deux tables "en même temps".

    Mais d'une manière générale, il faut éviter au maximum d'avoir des cardinalités mini à 1 des deux côtés d'une association.

  4. #4
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 11
    Points : 8
    Points
    8
    Par défaut
    Tout d'abord, merci beaucoup pour vos réponses.

    Il est vrai que je pourrais rajouter une colonne booléenne pour les adresses, mais en fait ce qui m'embête c'est que le client peut enregistrer autant d'adresses qu'il le souhaite, et en choisir une pour la rendre "principale" à tout moment, donc le caractère "principal" d'une l'adresse dépend plus du client que de l'adresse en soi (enfin je trouve ^^).

    Pour les paniers, ma logique était différente, car lorsqu'un client veut mettre des objets dans son panier, un panier est automatiquement créé, et se remplit. Puis le client peut enregistrer ce panier (ce qui lui enlève sa propriété "temporaire"), et un nouveau panier vide lui est alloué. Cette fois, par contre, il me semble plus logique de rajouter une colonne temporaryCart dans ma table Carts (comme vous l'avez proposé).

    Pensez-vous que je devrais faire la même chose pour les deux tables Carts et Addresses, en ajoutant une colonne booléenne ?

  5. #5
    Membre expérimenté
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Mayenne (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2010
    Messages : 793
    Points : 1 327
    Points
    1 327
    Par défaut
    Pour moi la notion de temporaire signifie que l'on n'a rien en base.
    A quoi te servent les paniers temporaires et sauvegardés ?
    Un client a la possibilité de sauver plusieurs paniers et les recharger par la suite ?
    Le panier temporaire est rechargé si le client quitte le site et revient dessus ?
    Si oui, effectivement le fonctionnement est pas mal.

    Dans ce cas tu peux alors ajouter un champs dans client (0,1) qui correspond à l'ID du panier temporaire.
    De même pour l'adresse principale.
    Et du côté des paniers et des adresses tu sais à quel client ils appartiennent puisque dans la table tu as l'id du client.

  6. #6
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 801
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    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 801
    Points : 34 063
    Points
    34 063
    Billets dans le blog
    14
    Par défaut
    Citation Envoyé par Naoris Voir le message
    Il est vrai que je pourrais rajouter une colonne booléenne pour les adresses, mais en fait ce qui m'embête c'est que le client peut enregistrer autant d'adresses qu'il le souhaite, et en choisir une pour la rendre "principale" à tout moment, donc le caractère "principal" d'une l'adresse dépend plus du client que de l'adresse en soi (enfin je trouve ^^).
    Donc c'est bien l'adresse qui dépend du client et pas le contraire et l'information doit se situer dans l'adresse et pas dans le client.
    La seule "contrainte" est que si le client change d'adresse principale, il faut passer l'ancienne adresse de mainAddress = 1 à mainAddress = 0. Un trigger fait ça sans problème.

    Pensez-vous que je devrais faire la même chose pour les deux tables Carts et Addresses, en ajoutant une colonne booléenne ?
    Oui je reste favorable à la colonne booléenne dans les deux tables cart et address.

    Au passage, il est d'usage de nommer les tables au singulier, tout comme les entités types dans le MCD.

  7. #7
    Membre expérimenté
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Mayenne (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2010
    Messages : 793
    Points : 1 327
    Points
    1 327
    Par défaut
    C'est tout de même moins contraignant, je pense, d'ajouter des clés étrangères dans client pour l'adresse principale et le panier temporaire.
    Au niveau des contraintes on a directement la contraint d'unicité sans trigger.
    Et au niveau des deux tables ça fait une info de moins, il vaut mieux 2 champs en + par client et 1 en mois par adresse et panier sachant qu'on peut avoir plusieurs adresses et paniers.

  8. #8
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 801
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    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 801
    Points : 34 063
    Points
    34 063
    Billets dans le blog
    14
    Par défaut
    Sauf qu'on retombe sur le schéma de départ et donc l'association à cardinalités (1,1 - 1,1) que tu critiquais dans ta première réponse !

  9. #9
    Membre expérimenté
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Mayenne (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2010
    Messages : 793
    Points : 1 327
    Points
    1 327
    Par défaut
    Absoluement pas !!!
    ça donne deux relations
    Client possède 0 ou 1 Panier temporaire (adresse principale)
    Client possède 0 ou n Paniers (adresses)

  10. #10
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 453
    Points : 18 388
    Points
    18 388
    Par défaut
    C'est une relation (0,1)-(1,1), un client qui n'a pas fait de commande n'a pas de panier, un client qui n'a pas encore renseigné d'adresse n'a pas d'adresse principale.

    Il suffit que les clefs étrangères de la table clients possèdent la propriété NULL.

  11. #11
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 801
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    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 801
    Points : 34 063
    Points
    34 063
    Billets dans le blog
    14
    Par défaut
    A -0,1----associer----1,1- B => clé étrangère dans B !

    Et les clés étrangères nullables, c'est mal !

  12. #12
    Membre expérimenté
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Mayenne (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2010
    Messages : 793
    Points : 1 327
    Points
    1 327
    Par défaut
    Je ne suis pas non plus un spécialiste SQL, mais il me semble que ce que Waldar a écrit correspond à ce que je pensais.
    Après est-ce mal ou non une clé étrangère nullable, je ne sais pas, peut être mais alors je suis preneur pour que l'on m'explique.

    Ta relation, selon ma vision des choses, est un mélange des 2 relations nécessaires.
    Le fait de posséder un panier temporaire (ou une adresse principale) est une relation
    Le fait d'appartenir à un client en est une autre.
    Par contre effectivement, pour être adresse principale (ou panier temporaire) d'un client, il faut lui appartenir, il faut tenir compte de cette contrainte.

  13. #13
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 453
    Points : 18 388
    Points
    18 388
    Par défaut
    Je ne vois pas en quoi une clef étrangère nullable serait mal, tant au niveau physique que conceptuel !

  14. #14
    Membre émérite Avatar de pacmann
    Homme Profil pro
    Consulté Oracle
    Inscrit en
    Juin 2004
    Messages
    1 626
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consulté Oracle
    Secteur : Distribution

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 626
    Points : 2 845
    Points
    2 845
    Par défaut
    Salut !
    Une clef étrangère nullable c'est choquant seulement dans la mesure où NULL est choquant tout court. Ni plus ni mois.

  15. #15
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 11
    Points : 8
    Points
    8
    Par défaut
    Oula, je sens qu'on s'engueule à cause de moi ><

    Sinon, j'ai l'impression que le coup des relations que décrit asmduty :

    Client possède 0 ou 1 Panier temporaire (adresse principale)
    Client possède 0 ou n Paniers (adresses)

    revient à mon problème du début, non ?
    Je n'ai peut-être pas compris, mais comme j'avais prévu que l'adresse principale et le panier temporaire soient initialement à NULL, je trouvais que mon schéma fonctionnait. Mais mon souci est que je n'arrive pas à déclarer mes tables, car je ne sais pas quelle table déclarer en premier, il y a toujours une clé étrangère qui fait coincer le script.

    Après, peut-être que je n'ai rien compris du tout ^^

    Ce que propose CinePhil marcherait aussi, mais j'aurais l'impression d'utiliser de la place en plus, sans pour autant augmenter la quantité d'information dans ma base.

    Bon, sinon sur les clés étrangères nullables, moi ça me choquait pas, mais je suis loin d'être un expert...

  16. #16
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 453
    Points : 18 388
    Points
    18 388
    Par défaut
    Citation Envoyé par Naoris Voir le message
    Mais mon souci est que je n'arrive pas à déclarer mes tables, car je ne sais pas quelle table déclarer en premier, il y a toujours une clé étrangère qui fait coincer le script.
    Il faut en effet créer les choses dans l'ordre.
    Ceci fonctionne avec Oracle, ça ne doit pas être loin de l'équivalent MySQL :
    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
    CREATE TABLE Client
    (
       idClient        INT NOT NULL
     , idMainAdresse   INT     NULL
     , idTemporaryCart INT     NULL
     , CONSTRAINT PK_Client PRIMARY KEY (idClient)
    );
     
    CREATE TABLE Cart
    (
       idCart   INT NOT NULL
     , idClient INT NOT NULL
     , CONSTRAINT PK_Cart PRIMARY KEY (idCart)
     , CONSTRAINT FK_Cart_Client FOREIGN KEY (idClient) REFERENCES Client (idClient)
    );
     
    CREATE TABLE Adresse
    (
       idAdresse INT NOT NULL
     , idClient  INT NOT NULL
     , CONSTRAINT PK_Adresse PRIMARY KEY (idAdresse)
     , CONSTRAINT FK_Adresse_Client FOREIGN KEY (idClient) REFERENCES Clients (idClient)
    );
     
    ALTER TABLE Client
    ADD CONSTRAINT FK_Client_Adresse_Main FOREIGN KEY (idMainAdresse)   REFERENCES Adresse (idAdresse)
    ADD CONSTRAINT FK_Client_Cart_Temp    FOREIGN KEY (idTemporaryCart) REFERENCES Cart    (idCart);

  17. #17
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 801
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    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 801
    Points : 34 063
    Points
    34 063
    Billets dans le blog
    14
    Par défaut
    Ce que propose CinePhil marcherait aussi, mais j'aurais l'impression d'utiliser de la place en plus, sans pour autant augmenter la quantité d'information dans ma base.
    Je me base sur les types de MySQL mais ça doit être à peu près pareil dans d'autres SGBD. Une clé étrangère entière occupe 4 octets. Un booléen n'occupe qu'un octet.

    Avec ta structure, si un client a une adresse principale et une adresse secondaire, le stockage de l'information nécessaire pour ces deux adresses, en ne prenant en compte que la partie adresse principale / adresse non principale, occupe 4 octets dans la table client pour stocker l'identifiant de l'adresse principale.
    Avec ma structure la même distinction entre les deux adresses occupe deux fois un octet dans la table adress, soit deux fois moins d'octets.
    En terme de place, ton modèle ne devient avantageux qu'à partir de 5 adresses pour un client. Quelle proportion de clients auras-tu avec plus de 4 adresses ?

  18. #18
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 453
    Points : 18 388
    Points
    18 388
    Par défaut
    Mais il ne pas oublier le coût du trigger qui vérifie qu'il n'y a qu'une seule adresse principale par client !

  19. #19
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 801
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    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 801
    Points : 34 063
    Points
    34 063
    Billets dans le blog
    14
    Par défaut
    Le trigger n'intervient qu'à l'insertion ou à la mise à jour mais ne prend pas de place en terme de stockage de données.

  20. #20
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 11
    Points : 8
    Points
    8
    Par défaut
    Bon, finalement je crois que je vais faire comme Waldar l'a expliqué, en ajoutant les contraintes après la création des tables. Merci Waldar !

    Merci beaucoup aux autres aussi, notamment CinePhil, tu m'as appris pas mal de choses ;-) (je ne connaissais pas du tout la taille des clés étrangères).

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. MySQL : insertion dans table avec clés étrangères
    Par chatmi dans le forum Requêtes
    Réponses: 7
    Dernier message: 22/06/2012, 15h36
  2. Réponses: 4
    Dernier message: 28/01/2010, 21h07
  3. Récuperer différence entre deux tables avec JOIN
    Par Takumi dans le forum Requêtes
    Réponses: 6
    Dernier message: 17/08/2009, 22h59
  4. Réponses: 1
    Dernier message: 11/06/2009, 23h39
  5. Relation entre tables avec clés différentes
    Par lylandra6 dans le forum Requêtes et SQL.
    Réponses: 2
    Dernier message: 22/09/2008, 23h01

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