web-dev-qa-db-fra.com

Puis-je avoir plusieurs clés primaires dans une seule table?

Puis-je avoir plusieurs clés primaires dans une seule table?

356
vaithi

Une table peut avoir une clé primaire composée , 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.

519
Adam Pierce

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

Vous pouvez également avoir des index uniques sur votre table, ce qui fonctionnera un peu comme une clé primaire en ce sens qu'ils appliqueront des valeurs uniques et accéléreront l'interrogation de ces valeurs.

182
RB.

Une table peut avoir plusieurs clés candidates. Chaque clé candidate est une colonne ou un ensemble de colonnes UNIQUE, prises ensemble, et aussi NOT NULL. Par conséquent, il suffit de spécifier les valeurs de toutes les colonnes d'une clé candidate pour déterminer s'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 relationnel.

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 les clés étrangères de la table référencent la clé primaire plutôt que toute autre clé candidate.

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

34
Walter Mitty

C’est la réponse à la fois à la question principale et à celle de @ Kalmi:

Quel serait l'intérêt d'avoir plusieurs colonnes auto-générées?

Ce code ci-dessous a une clé primaire composite. Une de ses colonnes est auto-incrémentée. Cela fonctionnera uniquement 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 en tant que 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 |
+--------+----+---------+
13
Eye

La Clé primaire est une notation très malheureuse, à cause de la connotation de "Primaire" et de l'association subconsciente en conséquence avec le modèle logique. J'évite donc de l'utiliser. Au lieu de cela, je me réfère à la clé de substitution du modèle physique et à la (aux) clé (s) naturelle (s) du modèle logique.

Il est important que le modèle logique de chaque entité ait au moins un ensemble "d'attributs commerciaux" comprenant une clé pour l'entité. Boyce, Codd, Date et autres se réfèrent à ceux-ci dans le modèle relationnel en tant que clés candidates. Lorsque nous construisons ensuite des tables pour ces entités, leurs clés candidates deviennent des clés naturelles dans ces tables. Ce n'est que par l'intermédiaire de ces clés naturelles que les utilisateurs sont en mesure d'identifier de manière unique les lignes dans les tables. Les clés de substitution doivent toujours être cachées des utilisateurs. En effet, les clés de substitution n'ont aucune signification professionnelle.

Cependant, le modèle physique de nos tables sera souvent 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é (ignorer les tables implémentées en tant que tas pendant un moment). Lorsque nos clés naturelles disponibles sont larges, cela (1) élargit la largeur de nos nœuds feuilles non groupés, augmentant ainsi 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 la déréglage de notre index cluster en augmentant la hauteur et la taille de l'index, augmentant ainsi les exigences en matière de lecture et de stockage pour nos index en cluster; et (3) augmente les exigences de cache pour nos index clusterisés. chasser d'autres index et données 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'elle est définie en tant que clé de cluster afin d'être utilisée 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 liées, tous ces inconvénients disparaissent. Nos fan-outs d'index en cluster augmentent encore pour réduire la hauteur et la taille des index en cluster, la charge de cache pour nos index en cluster, réduire le nombre de lectures lors de l'accès aux données via n'importe quel mécanisme (analyse d'index, recherche d'index, recherche de clé non-cluster ou recherche de clé étrangère). et réduire les besoins de stockage pour les index en cluster et non-cluster de nos tables.

Notez que ces avantages ne se produisent que lorsque la clé de substitution est à la fois petite et la clé de clustering. Si un GUID est utilisé comme clé de regroupement, 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, alors le RowID sur 8 octets (tas) sera utilisé pour les recherches de clé, ce qui est meilleur qu'un GUID16 à 16 octets mais moins performant qu'un entier à 4 octets.

Si un GUID doit être utilisé en raison de contraintes commerciales, il vaut la peine de rechercher une meilleure clé de clustering. Si, par exemple, un identificateur de site de petite taille et un "numéro de séquence de site" sur 4 octets sont réalisables, cette conception peut offrir de meilleures performances qu'un GUID en tant que clé de substitution.

Si les conséquences d'un tas (hash join, peut-être) en font le stockage préféré, les coûts d'une clé de regroupement plus large doivent être pris en compte dans l'analyse des 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 nom de famille Unicode long et un entier de 4 octets, il serait souhaitable (1) d'appliquer cette contrainte de manière déclarative " ADD CONSTRAINT pk_PersonID UNIQUE NON CLUSTERED (P_Id, LastName) "et (2) déclarent séparément une petite clé de substitution comme étant le" clé primaire "d'un index clusterisé. Il convient de noter qu'Anita souhaite éventuellement uniquement ajouter le nom LastName à cette contrainte afin de créer un champ couvert, ce qui est inutile dans un index clusterisé, car TOUS les champs en sont couverts.

La possibilité dans SQL Server de désigner une clé primaire comme non clusterisée est une circonstance historique malheureuse, en raison de la confusion entre le sens de "clé naturelle ou candidate préférée" (du modèle logique) et le sens de "clé de recherche stockée" du paramètre Physique. Modèle. Si j'ai bien compris, SYBASE SQL Server utilisait toujours à l'origine un RowID de 4 octets, qu'il s'agisse d'un tas ou d'un index clusterisé, en tant que "clé de recherche stockée" du modèle physique.

7
Pieter Geerkens

Comme indiqué par les autres, il est possible d'avoir des clés primaires multi-colonnes. Il faut noter cependant que si vous avez des dépendances fonctionnelles qui ne sont pas introduits par une clé, vous devriez considérer 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_code est associé à un area et il existe donc une dépendance fonctionnelle interne entre Zip_code -> area.

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

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

Pour que cela soit cohérent avec le troisième forme normale .

6
Yet Another Geek

(Ont étudié ces, beaucoup)

Il ne peut y avoir qu'une seule clé primaire.
Mais vous pouvez avoir plusieurs clés alternatives.

En simple c'est le cas:

  • peut être multiple Clés candidates (colonnes minimales, pour identifier de manière unique une ligne) dans une table.

    • Une des clés candidates est choisie spécifiquement et est appelée clé primaire
    • Toutes autres clés candidates sont appelées Touches alternatives
      • Les clés primaires et alternatives peuvent être clés composées s (2 colonnes ou plus)

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

5

Une clé primaire est la clé qui identifie de manière unique un enregistrement et est utilisée dans tous les index. C'est pourquoi vous ne pouvez pas en avoir plus d'un. C'est aussi généralement la clé utilisée pour joindre des tables enfants, mais ce n'est pas une obligation. Le véritable objectif d’une PC est de s’assurer que quelque chose vous permet d’identifier un enregistrement de manière unique, afin que les modifications de données affectent l’enregistrement correct et que des index puissent être créés.

Cependant, vous pouvez placer plusieurs champs dans une clé primaire (une clé 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 vous éviter de devoir faire des jointures dans certaines des tables enfants. base de cas. Lorsque vous procédez ainsi, chaque champ n'est pas unique, mais sa combinaison l'est. Si un ou plusieurs champs d'une clé composite doivent également être uniques, vous avez besoin d'un index unique. Il est cependant probable que si un domaine est unique, il s'agit d'un meilleur candidat pour la PK.

Maintenant, parfois, vous avez plus d'un candidat pour le PK. Dans ce cas, choisissez-en une 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 clé physique. Si les données doivent être uniques, il faut un index unique, qu’il s’agisse ou non de la PK. C'est un problème d'intégrité des données. (Notez que ceci est également vrai chaque fois que vous utilisez une clé de substitution; les personnes rencontrent des problèmes avec les clés de substitution car elles oublient de créer des index uniques sur les clés candidates.)

Il arrive parfois que vous vouliez plus d'une clé de substitution (qui sont généralement la clé PK si vous en avez). Dans ce cas, ce que vous voulez n'est pas plus de PK, mais davantage 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 le contourner. Commencez par déterminer si le deuxième champ peut être calculé en fonction de la première clé générée automatiquement (Champ1 * -1 par exemple) ou si la nécessité d'une deuxième clé générée automatiquement signifie que vous devez réellement créer une table liée. Les tables associées peuvent être dans une relation un à un. Pour ce faire, vous devez ajouter le PK de la table parent à la table enfant, puis ajouter le nouveau champ généré automatiquement à la table, puis les champs appropriés pour cette table. Choisissez ensuite l'une des deux clés comme clé de clé et mettez un index unique sur l'autre (le champ généré automatiquement ne doit pas nécessairement être une clé de clé). 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.

2
HLGEM

Avoir deux clés primaires en même temps, n'est pas possible. Mais (en supposant que vous n’ayez pas compliqué la tâche avec une clé composite), vous pouvez 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 une base de données relationnelle, une "super clé" est un sous-ensemble d'attributs qui identifient de manière unique un tuple ou une ligne dans une table. Une "clé" est une "super clé" qui a pour propriété supplémentaire de supprimer tout attribut de la clé, qui ne fait plus de cette clé une "super clé" (ou simplement une "clé" est une super clé minimale). S'il y a plus de clés, toutes sont 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 relation ou une table unique est un conflit.

Certaines personnes utilisent le terme "clé primaire" pour désigner exactement une colonne entière dont les valeurs sont générées par un mécanisme automatique. Par exemple, AUTO_INCREMENT dans MySQL ou IDENTITY dans Microsoft SQL Server. Utilisez-vous une clé primaire dans ce sens?

Si tel est le cas, la réponse dépend de la marque de base de données utilisée. 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 générées automatiquement dans une table.

2
Bill Karwin

De bonnes réponses techniques ont été données mieux que je ne peux le faire. Je suis seulement peut 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 pourquoi ce n'est pas acceptable.
  2. Creusez plus dans la documentation/articles de journaux/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. Attendez-vous toujours et essayez de créer une solution adaptative.

J'espère que ça aidera quelqu'un.

1
Tom Lime