Puis-je avoir plusieurs clés primaires dans une même table?
Puis-je avoir plusieurs clés primaires dans une même table?
Réponses:
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.
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.
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.
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 |
+--------+----+---------+
(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.
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
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_code
est 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 .
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.
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_INCREMENT
dans 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.
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.
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.
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.
J'espère que cela aidera quelqu'un.
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)
);