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 :

Une colonne peut-elle être clé primaire et clé étrangère ?


Sujet :

Langage SQL

  1. #1
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 442
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 442
    Points : 5 800
    Points
    5 800
    Billets dans le blog
    1
    Par défaut Une colonne peut-elle être clé primaire et clé étrangère ?
    Bonjour,

    j'ai une table dont une colonne appartient à la clé étrangère (celle-ci porte sur 2 colonnes) et à laquelle j'ai aussi attribué une clé étrangère :
    table `license`:
    Code sql : 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
    DROP TABLE IF EXISTS `license`;
    CREATE TABLE `license` (
      `id_SESA` int(6) NOT NULL,
      `application_key` smallint(2) NOT NULL,
      `currently_active` tinyint(1) DEFAULT NULL,
      `activate_date` date DEFAULT NULL,
      `deactivate_date` date DEFAULT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
     
    --
    -- Index pour la table `license`
    --
    ALTER TABLE `license`
      ADD PRIMARY KEY (`id_SESA`,`application_key`) USING BTREE,
      ADD KEY `fk_application` (`application_key`);
     
    --
    -- Contraintes pour la table `license`
    --
    ALTER TABLE `license`
      ADD CONSTRAINT `fk_application` FOREIGN KEY (`application_key`) REFERENCES `application` (`application_key`),
      ADD CONSTRAINT `fk_user` FOREIGN KEY (`id_SESA`) REFERENCES `user` (`sesa`);
    un essai dans PhpMyadmin d'insertion dans cette table semble indiquer que c'est autorisé (clé primaire + clé étrangère). Me confirmez-vous que oui ?

    Et d'ailleurs, ceci étant le résultat d'un export, comment se fait-il qu'on trouve 2 fois la déclaration de `fk_application` ?

  2. #2
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 099
    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 099
    Points : 28 400
    Points
    28 400
    Par défaut
    Dans ton cas, la colonne application_key n'est pas à la fois clé primaire et clé étrangère ; elle est constituante de la clé primaire, qui comporte deux colonnes.
    Mais même si elle était l'unique constituant de la clé primaire, cela serait aussi autorisé.
    C'est d'ailleurs ce que l'on retrouve dans les cas de formalisation d'héritage.

    Il n'y a pas de double déclaration de fk_application. Il y a d'une part un index et de l'autre une contrainte d'intégrité référentielle.
    Il faudrait d'ailleurs se poser la question si l'index est réellement utile en fonction des requêtes qui seront effectuées sur cette table.

  3. #3
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 442
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 442
    Points : 5 800
    Points
    5 800
    Billets dans le blog
    1
    Par défaut
    Merci pour la réponse.

    Oui, l'index sur la colonne application_key ne servait à rien (je me demande d'où il vient) et je l'ai supprimé.

    En fait, j'ai 2 colonnes constituantes de la clé primaire : id_SESA et application_key et elles sont déclarées toutes les 2 comme clé étrangère ! ( id_SESA vers la table user et application_key vers la table application )

  4. #4
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 168
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Février 2010
    Messages : 4 168
    Points : 7 421
    Points
    7 421
    Billets dans le blog
    1
    Par défaut
    La réponse au titre est OUI, c'est ce qu'on fait dans le cadre de l'héritage.

    Par exemple une table "tiers" :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    create table tiers
    (
       id int primary key identity,
       nom char(30) not null
    );

    Une table "client" qui étend la table "tiers" :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    create table client
    (
       id int primary key references tiers(id),
       prenom char(30) not null
    );

    Un client X est de facto un tiers X : on utilise donc le même identifiant, et on indique qu'un client est forcément lié à un tiers.

    Ensuite, ton cas précis (clé primaire composée de deux clés étrangères) est typiquement le cas d'une table de jointure.
    Par exemple :
    Code sql : 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
     
    create table client
    (
       id int primary key identity,
       nom char(30) not null
    );
     
    create table voiture
    (
       id int primary key identity,
       immatriculation char(7) not null
    );
     
    create table location
    (
       id_client int not null references client(id),
       id_voiture int not null references voiture(id),
       debut date not null,
       fin date not null,
       primary key (id_client, id_voiture)
    );

    => Une location est identifiée par un client et une voiture. Avec une date de début et de fin... attention cependant, dans ce cas un client ne peu louer qu'une seule fois chaque voiture, c'est pas forcément ce qu'on veut

    PS : dans tous les cas, c'est une pratique à éviter cependant. Il faut toujours privilégier une clé unitaire et dénuée de sens. Donc créer une colonne "id" clé primaire, et mettre une contrainte d'unicité sur les deux clé étrangères. Ce sera plus performant, surtout si tu insères beaucoup de données et que tu as d'autres index sur ta table.

  5. #5
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 442
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 442
    Points : 5 800
    Points
    5 800
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par StringBuilder Voir le message
    PS : dans tous les cas, c'est une pratique à éviter cependant. Il faut toujours privilégier une clé unitaire et dénuée de sens. Donc créer une colonne "id" clé primaire, et mettre une contrainte d'unicité sur les deux clé étrangères. Ce sera plus performant, surtout si tu insères beaucoup de données et que tu as d'autres index sur ta table.
    Est-ce que ta remarque concerne aussi ma table et que je devrais aussi ajouter une colonne id dénuée de sens et qui servirait de clé primaire ?

    Sinon, mettre une clé d'unicité sur les 2 colonnes-clés étrangères, ça me surprend, comme un utilisateur (identifié par la colonne id_SESA) peut posséder une licence de plusieurs applications donc apparaître dans plusieurs enregistrements, et pareil pour la colonne application_key, vu que plusieurs utlisateurs peuvent détenir une licence pour la même application et que donc la même valeur pour la colonne application_key apparaîtra aussi dans plusieurs enregistrements...

  6. #6
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Bonjour

    Citation Envoyé par StringBuilder Voir le message
    PS : dans tous les cas, c'est une pratique à éviter cependant. Il faut toujours privilégier une clé unitaire et dénuée de sens. Donc créer une colonne "id" clé primaire, et mettre une contrainte d'unicité sur les deux clé étrangères. Ce sera plus performant, surtout si tu insères beaucoup de données et que tu as d'autres index sur ta table.
    Même si la remarque est vraie d'un point de vue général, en l’occurrence, je mettrais un bémol.
    Sur une telle table (associative sur seulement deux FK), laisser la clef primaire sur le couple de clefs étrangères permet d'avoir un index cluster (et donc forcément couvrant) pour la moitié (voire bien plus selon l'usage) des requêtes, et il suffit de placer un deuxième index sur la deuxième clef pour couvrir tous les cas, et éliminer les recherches de clef, souvent couteuses.

  7. #7
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 849
    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 849
    Points : 52 975
    Points
    52 975
    Billets dans le blog
    6
    Par défaut
    C'est systématique dès que l'on a une entité fiable :
    1) le cas de l'héritage
    2) le cas de l'association identifiante

    Voici un extrait de mon nouveau livre à paraitre sur le langage SQL (passage du MCD au MLD dans le cas de l'héritage) :
    Nom : Le langage SQL, théorie et pratique - extrait CH2 héritage.jpg
Affichages : 4893
Taille : 441,5 Ko

    A +

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

Discussions similaires

  1. Une machine téléportée peut-elle être réutilisable ?
    Par mtiburs dans le forum VirtualBox
    Réponses: 1
    Dernier message: 24/09/2013, 19h07
  2. Une variable créée peut-elle être liée ?
    Par Baldenschaft dans le forum Deski
    Réponses: 2
    Dernier message: 29/08/2011, 14h28
  3. une colonne peut-elle être une référence à une table?
    Par professeur shadoko dans le forum Langage SQL
    Réponses: 17
    Dernier message: 24/06/2010, 15h25
  4. Réponses: 13
    Dernier message: 15/01/2007, 02h30
  5. Une Foreign Key peut-elle être null ?
    Par bassim dans le forum Firebird
    Réponses: 9
    Dernier message: 21/11/2006, 20h20

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