Puis-je avoir plusieurs clés primaires dans une même table?

Réponses:

559

Une table peut avoir une clé primaire composite qui est une clé primaire composée de deux colonnes ou plus. Par exemple:

CREATE TABLE userdata (
  userid INT,
  userdataid INT,
  info char(200),
  primary key (userid, userdataid)
);

Mise à jour: voici un lien avec une description plus détaillée des clés primaires composites.

Adam Pierce
la source
2
Dans cet exemple, les deux ID utilisateur et ID utilisateur sont nécessaires pour identifier / rechercher une ligne unique. Je ne sais pas quelle était l'intention du PO, mais je suis venu ici pour voir si je pouvais identifier de manière unique une rangée avec l'un d'un jeu de clés. Par exemple, je voudrais identifier un utilisateur unique avec un nom d'utilisateur OU un ID utilisateur, sans avoir besoin des deux. Je suppose que la réponse de RB à des index uniques ferait l'affaire.
Burrito
1
@Benitok Comme mentionné dans la réponse de RB. , Vous pouvez utiliser des index uniques pour faire ce que vous recherchez (une colonne indexée unique indépendante des autres colonnes indexées uniques sur la même table). Assurez-vous de consulter votre version spécifique du manuel de SQL pour plus de détails sur la syntaxe exacte du langage utilisé.
4h du
195

Vous ne pouvez avoir qu'une seule clé primaire, mais vous pouvez avoir plusieurs colonnes dans votre clé primaire.

Vous pouvez également avoir des index uniques sur votre table, qui fonctionneront un peu comme une clé primaire dans la mesure où ils appliqueront des valeurs uniques et accéléreront l'interrogation de ces valeurs.

RB.
la source
39

Une table peut avoir plusieurs clés candidates. Chaque clé candidate est une colonne ou un ensemble de colonnes UNIQUES, prises ensemble et également NON NULES. Ainsi, la spécification de valeurs pour toutes les colonnes d'une clé candidate suffit pour déterminer qu'il existe une ligne qui répond aux critères, ou aucune ligne du tout.

Les clés candidates sont un concept fondamental dans le modèle de données relationnelles.

Il est courant, si plusieurs clés sont présentes dans une même table, de désigner l'une des clés candidates comme clé primaire. Il est également courant de faire en sorte que toute clé étrangère de la table fasse référence à la clé primaire, plutôt qu'à toute autre clé candidate.

Je recommande ces pratiques, mais rien dans le modèle relationnel ne nécessite la sélection d'une clé primaire parmi les clés candidates.

Walter Mitty
la source
5
D'accord. Toutes les clés sont égales (aucune n'est «principale») dans le modèle logique. Le choix de la clé dans l'implémentation physique qui obtient la désignation de CLÉ PRIMAIRE est arbitraire et dépend du fournisseur / produit.
quand
3
Je dirais que cela dépend du concepteur de base de données.
Walter Mitty
Je viens de rencontrer un cas d'utilisation où cela est nécessaire. J'ai une table qui sera créée / gérée par Entity Framework - qui, pour autant que je sache, ne prend pas en charge les contraintes composites uniques de clé non primaire à l'heure actuelle. Cependant, il prend en charge les clés primaires composites. Les données vont également être liées à un système de base de données distant qui ne prend pas du tout en charge les clés composites. Je suis allé avec la création d'un PK composite dans EF, mais aussi l'ajout d'une colonne GUID non nullable que l'autre système peut utiliser pour s'identifier de manière unique.
Chris Nevill
2
Chris, j'ai dit que le modèle relationnel ne nécessite pas de clés primaires. Je n'ai pas dit si un outil pouvait en avoir besoin. Mais je comprends votre point.
Walter Mitty
Je pense qu'il est nécessaire que le PK soit minimal, c'est-à-dire qu'il utilise le moins de colonnes pour identifier de manière unique chaque enregistrement.
gary
14

Ceci est la réponse à la fois à la question principale et à la question de @ Kalmi de

Quel serait l'intérêt d'avoir plusieurs colonnes à génération automatique?

Ce code ci-dessous a une clé primaire composite. Une de ses colonnes est incrémentée automatiquement. Cela ne fonctionnera que dans MyISAM. InnoDB générera une erreur " ERREUR 1075 (42000): définition de table incorrecte; il ne peut y avoir qu'une seule colonne automatique et elle doit être définie comme une clé ".

DROP TABLE IF EXISTS `test`.`animals`;
CREATE TABLE  `test`.`animals` (
  `grp` char(30) NOT NULL,
  `id` mediumint(9) NOT NULL AUTO_INCREMENT,
  `name` char(30) NOT NULL,
  PRIMARY KEY (`grp`,`id`)
) ENGINE=MyISAM;

INSERT INTO animals (grp,name) VALUES
    ('mammal','dog'),('mammal','cat'),
    ('bird','penguin'),('fish','lax'),('mammal','whale'),
    ('bird','ostrich');

SELECT * FROM animals ORDER BY grp,id;

Which returns:

+--------+----+---------+
| grp    | id | name    |
+--------+----+---------+
| fish   |  1 | lax     |
| mammal |  1 | dog     |
| mammal |  2 | cat     |
| mammal |  3 | whale   |
| bird   |  1 | penguin |
| bird   |  2 | ostrich |
+--------+----+---------+
Œil
la source
2
Cela fonctionne si vous spécifiez d'abord la colonne d'incrémentation automatique dans la définition de clé primaire. (Peut-être que cela a changé, je viens de le tester en 5.6)
CTarczon
11

(Je les ai beaucoup étudiés)

Clés candidates - Combinaison minimale de colonnes requise pour identifier de manière unique une ligne de tableau.
Clés composées - 2 colonnes ou plus.

  • Plusieurs clés de candidat peuvent exister dans une table.
    • CLÉ primaire - Une seule des clés candidates choisie nous avons
    • Touches alternatives - Toutes les autres clés candidates
      • La clé primaire et la clé alternative peuvent être des clés composées

Sources:
https://en.wikipedia.org/wiki/Superkey
https://en.wikipedia.org/wiki/Candidate_key
https://en.wikipedia.org/wiki/Primary_key
https://en.wikipedia.org / wiki / Compound_key

Manohar Reddy Poreddy
la source
6

Comme indiqué par les autres, il est possible d'avoir des clés primaires multi-colonnes. Il faut cependant noter que si vous avez des dépendances fonctionnelles qui ne sont pas introduites par une clé, vous devriez envisager de normaliser votre relation.

Exemple:

Person(id, name, email, street, zip_code, area)

Il peut y avoir une dépendance fonctionnelle entre id -> name,email, street, zip_code and area Mais souvent, un zip_codeest associé à unarea et donc il y a une dépendance fonctionnelle interne entrezip_code -> area .

Ainsi, on peut envisager de le diviser en une autre table:

Person(id, name, email, street, zip_code)
Area(zip_code, name)

Pour qu'il soit cohérent avec la troisième forme normale .

Encore un autre geek
la source
6

La clé primaire est une notation très malheureuse, en raison de la connotation de «primaire» et de l'association subconsciente en conséquence avec le modèle logique. J'évite donc de l'utiliser. Je fais plutôt référence à la clé de substitution du modèle physique et à la ou aux clés naturelles du modèle logique.

Il est important que le modèle logique de chaque entité ait au moins un ensemble "d'attributs commerciaux" qui comprennent une clé pour l'entité. Boyce, Codd, Date et al se réfèrent à ceux-ci dans le modèle relationnel comme clés candidates. Lorsque nous créons ensuite des tables pour ces entités, leurs clés candidates deviennent des clés naturelles dans ces tables. Ce n'est que par le biais de ces clés naturelles que les utilisateurs peuvent identifier de manière unique les lignes des tables; car les clés de substitution doivent toujours être cachées aux utilisateurs. En effet, les clés de substitution n'ont aucune signification commerciale.

Cependant, le modèle physique de nos tables sera dans de nombreux cas inefficace sans clé de substitution. Rappelez-vous que les colonnes non couvertes pour un index non clusterisé ne peuvent être trouvées (en général) que via une recherche de clé dans l'index clusterisé (ignorez les tables implémentées en tas pour un moment). Lorsque nos clés naturelles disponibles sont larges, cela (1) élargit la largeur de nos nœuds terminaux non groupés, augmentant les exigences de stockage et les accès en lecture pour les recherches et les analyses de cet index non groupé; et (2) réduit le fan-out de notre index cluster augmentant la hauteur et la taille de l'index, augmentant à nouveau les lectures et les exigences de stockage pour nos index cluster; et (3) augmente les exigences de cache pour nos index clusterisés. chasser d'autres index et données hors du cache.

C'est là qu'une petite clé de substitution, désignée dans le SGBDR comme «la clé primaire», s'avère bénéfique. Lorsqu'il est défini comme clé de clustering, afin d'être utilisé pour les recherches de clé dans l'index clusterisé à partir d'index non clusterisés et les recherches de clé étrangère à partir de tables associées, tous ces inconvénients disparaissent. Nos ventilations d'index en cluster augmentent à nouveau pour réduire la hauteur et la taille de l'index en cluster, réduire la charge du cache pour nos index en cluster, réduire les lectures lors de l'accès aux données par n'importe quel mécanisme (que ce soit l'indexation, la recherche d'index, la recherche de clé non en cluster ou la recherche de clé étrangère) et diminuer les besoins de stockage pour les index cluster et non cluster de nos tables.

Notez que ces avantages se produisent uniquement lorsque la clé de substitution est à la fois petite et la clé de clustering. Si un GUID est utilisé comme clé de clustering, la situation sera souvent pire que si la plus petite clé naturelle disponible avait été utilisée. Si la table est organisée en tas, le RowID de 8 octets (tas) sera utilisé pour les recherches de clés, ce qui est meilleur qu'un GUID de 16 octets mais moins performant qu'un entier de 4 octets.

Si un GUID doit être utilisé en raison de contraintes métier, la recherche d'une meilleure clé de clustering en vaut la peine. Si, par exemple, un petit identifiant de site et un "numéro de séquence de site" de 4 octets sont réalisables, cette conception peut donner de meilleures performances qu'un GUID en tant que clé de substitution.

Si les conséquences d'un tas (jointure de hachage peut-être) en font le stockage préféré, alors les coûts d'une clé de clustering plus large doivent être équilibrés dans l'analyse de compromis.

Considérez cet exemple ::

ALTER TABLE Persons
ADD CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)

où le tuple " (P_Id, LastName) " nécessite une contrainte d'unicité et peut être un long nom Unicode plus un entier de 4 octets, il serait souhaitable (1) d'appliquer de manière déclarative cette contrainte comme " ADD CONSTRAINT pk_PersonID UNIQUE NONCLUSTERED (P_Id , LastName) "et (2) déclarent séparément une petite clé de substitution comme" clé primaire "d'un index clusterisé. Il convient de noter qu'Anita souhaite peut-être uniquement ajouter le nom de famille à cette contrainte afin d'en faire un champ couvert, ce qui n'est pas nécessaire dans un index clusterisé car TOUS les champs sont couverts par celui-ci.

La possibilité dans SQL Server de désigner une clé primaire comme non cluster est une circonstance historique malheureuse, en raison d'une fusion de la signification «clé naturelle ou candidate préférée» (du modèle logique) avec la signification «clé de recherche dans le stockage» du physique Modèle. D'après ce que je comprends, à l'origine, SYBASE SQL Server a toujours utilisé un RowID de 4 octets, que ce soit dans un segment de mémoire ou un index clusterisé, comme "clé de recherche dans le stockage" du modèle physique.

Pieter Geerkens
la source
3
Pouvez-vous traduire ceci en anglais!
Jasir
3

Certaines personnes utilisent le terme «clé primaire» pour désigner exactement une colonne entière qui obtient ses valeurs générées par un mécanisme automatique. Par exemple AUTO_INCREMENTdans MySQL ouIDENTITY dans Microsoft SQL Server. Utilisez-vous la clé primaire dans ce sens?

Si tel est le cas, la réponse dépend de la marque de base de données que vous utilisez. Dans MySQL, vous ne pouvez pas faire cela, vous obtenez une erreur:

mysql> create table foo (
  id int primary key auto_increment, 
  id2 int auto_increment
);
ERROR 1075 (42000): Incorrect table definition; 
there can be only one auto column and it must be defined as a key

Dans certaines autres marques de base de données, vous pouvez définir plusieurs colonnes de génération automatique dans une table.

Bill Karwin
la source
5
Quel serait l'intérêt d'avoir plusieurs colonnes à génération automatique?
Tarnay Kálmán
Je n'ai pas de cas d'utilisation en tête, mais s'il y avait un besoin, certaines marques de base de données prendraient cela en charge et d'autres non. C'est tout ce que je dis.
Bill Karwin
1
Voici un cas: dans une table de commandes, j'ai à la fois un ID (incrémenté automatiquement) et un ID externe (chaînes de type hachage), les deux devraient être uniques, donc théoriquement, vous pourriez dire qu'ils sont tous les deux "principaux". bien sûr, cela peut être fait avec un index unique secondaire mais c'est toujours un cas légitime (à mon humble avis)
Nir
2

Il n'est pas possible d'avoir deux clés primaires en même temps. Mais (en supposant que vous n'avez pas foiré le cas avec une clé composite), vous pourriez avoir besoin de rendre un attribut unique.

CREATE t1(
c1 int NOT NULL,
c2 int NOT NULL UNIQUE,
...,
PRIMARY KEY (c1)
);

Cependant, notez que dans la base de données relationnelle, une «super clé» est un sous-ensemble d'attributs qui identifie de manière unique un tuple ou une ligne dans une table. Une «clé» est une «super clé» qui possède une propriété supplémentaire qui supprime tout attribut de la clé, fait de cette clé plus une «super clé» (ou simplement une «clé» est une super clé minimale). S'il y a plus de clés, elles sont toutes des clés candidates. Nous sélectionnons l'une des clés candidates comme clé primaire. C'est pourquoi parler de plusieurs clés primaires pour une seule relation ou table est un conflit.

Rusiru Adithya Samarasinghe
la source
Wikipedia n'a pas de définition de «clé». De plus, la «suppression de tout attribut de la clé ne fait plus de cette clé une« super clé »» ne signifiait rien pour moi, car lorsque la suppression d'un attribut de la super clé peut toujours être une super clé.
Manohar Reddy Poreddy le
@ManoharReddyPoreddy Oui, dans ce cas, votre ensemble d'attributs n'est pas une «clé» mais une «super clé». Ce que je veux dire, c'est que si un ensemble d'attributs est une `` clé '', l'ensemble doit être minimal, ou l'ensemble doit avoir une propriété supplémentaire qui supprime tout attribut de l'ensemble fait que l'ensemble résultant n'est plus une `` super clé ''.
Rusiru Adithya Samarasinghe
On dirait que votre véritable sens de «clé» est Candidate_key ( en.wikipedia.org/wiki/Candidate_key ), peut-être faut-il le mentionner.
Manohar Reddy Poreddy
@ManoharReddyPoreddy Oui, je l'ai déjà mentionné dans ma réponse. "S'il y a plus de clés, toutes sont des clés candidates". Quoi qu'il en soit, merci pour votre avis.
Rusiru Adithya Samarasinghe
1. Lorsque vous mentionnez "S'il y a plus de clés, toutes sont des clés candidates", ... Voulez-vous dire autrement / sinon, ce ne sont pas des clés candidates? ... 2. Où est le reste? ... Sommes-nous la même page du tout?
Manohar Reddy Poreddy
1

Une clé primaire est la clé qui identifie de façon unique un enregistrement et est utilisée dans tous les index. C'est pourquoi vous ne pouvez pas en avoir plus d'un. Il s'agit également généralement de la clé utilisée pour joindre des tables enfants, mais ce n'est pas obligatoire. Le but réel d'un PK est de s'assurer que quelque chose vous permet d'identifier de manière unique un enregistrement afin que les modifications de données affectent l'enregistrement correct et que les index puissent être créés.

Cependant, vous pouvez mettre plusieurs champs dans une clé primaire (un PK composite). Cela rendra vos jointures plus lentes (surtout si ce sont des champs de type chaîne plus grands) et vos index plus grands, mais cela peut supprimer la nécessité de faire des jointures dans certaines des tables enfants.Pour ce qui est des performances et de la conception, prenez-le sur un cas en cas par cas. Lorsque vous effectuez cette opération, chaque champ lui-même n'est pas unique, mais leur combinaison l'est. Si un ou plusieurs des champs d'une clé composite doivent également être uniques, vous avez besoin d'un index unique dessus. Il est cependant probable que si un champ est unique, c'est un meilleur candidat pour le PK.

Maintenant, parfois, vous avez plus d'un candidat pour le PK. Dans ce cas, vous en choisissez un comme PK ou utilisez une clé de substitution (je préfère personnellement les clés de substitution pour cette instance). Et (c'est essentiel!) Vous ajoutez des index uniques à chacune des clés candidates qui n'ont pas été choisies comme PK. Si les données doivent être uniques, elles ont besoin d'un index unique, qu'il s'agisse du PK ou non. Il s'agit d'un problème d'intégrité des données. (Notez que cela est également vrai à chaque fois que vous utilisez une clé de substitution; les gens ont des problèmes avec les clés de substitution parce qu'ils oublient de créer des index uniques sur les clés candidates.)

Il y a parfois des moments où vous voulez plus d'une clé de substitution (qui sont généralement le PK si vous les avez). Dans ce cas, ce que vous voulez n'est pas plus de PK, mais plus de champs avec des clés générées automatiquement. La plupart des bases de données ne le permettent pas, mais il existe des moyens de contourner ce problème. Demandez-vous d'abord si le deuxième champ peut être calculé sur la base de la première clé auto-générée (Field1 * -1 par exemple) ou peut-être que la nécessité d'une deuxième clé auto-générée signifie vraiment que vous devez créer une table associée. Les tables associées peuvent être dans une relation un à un. Vous imposeriez cela en ajoutant le PK de la table parent à la table enfant, puis en ajoutant le nouveau champ généré automatiquement à la table, puis tous les champs appropriés pour cette table. Ensuite, choisissez l'une des deux clés comme PK et mettez un index unique sur l'autre (le champ généré automatiquement n'a pas besoin d'être un PK). Et assurez-vous d'ajouter le FK au champ qui se trouve dans la table parent. En général, si vous n'avez pas de champs supplémentaires pour la table enfant, vous devez examiner pourquoi vous pensez avoir besoin de deux champs générés automatiquement.

HLGEM
la source
0

De bonnes réponses techniques ont été données mieux que moi. Je peux seulement ajouter à ce sujet:

Si vous voulez quelque chose qui n'est pas autorisé / acceptable, c'est une bonne raison de prendre du recul.

  1. Comprenez au fond pourquoi ce n'est pas acceptable.
  2. Creusez plus dans la documentation / articles de revues / web et etc.
  3. Analyser / réviser la conception actuelle et signaler les principaux défauts.
  4. Considérez et testez chaque étape lors de la nouvelle conception.
  5. Ayez toujours hâte et essayez de créer une solution adaptative.

J'espère que cela aidera quelqu'un.

Tom Lime
la source
1
des conseils génériques (bien qu'utiles), pas une réponse à la question spécifique.
Bradford Needham
-3

Oui, c'est possible en SQL, mais nous ne pouvons pas définir plus d'une clé primaire dans MsAccess. Ensuite, je ne connais pas les autres bases de données.

CREATE TABLE CHAPTER (
    BOOK_ISBN VARCHAR(50) NOT NULL,
    IDX INT NOT NULL,
    TITLE VARCHAR(100) NOT NULL,
    NUM_OF_PAGES INT,
    PRIMARY KEY (BOOK_ISBN, IDX)
);
stema
la source
Une table SQL ne peut avoir qu'un seul PK.
philipxy