Au travail, nous avons une grande base de données avec des index uniques au lieu de clés primaires et tout fonctionne bien.
Je conçois une nouvelle base de données pour un nouveau projet et j'ai un dilemme:
Dans la théorie de la base de données, la clé primaire est un élément fondamental, ce n'est pas grave, mais dans les projets REAL, quels sont les avantages et les inconvénients des deux?
Qu'est-ce que vous utilisez dans les projets?
EDIT: ... et qu'en est-il des clés primaires et de la réplication sur un serveur MS SQL?
Qu'est-ce qu'un index unique?
Un index unique sur une colonne est un index sur cette colonne qui applique également la contrainte selon laquelle vous ne pouvez pas avoir deux valeurs égales dans cette colonne dans deux lignes différentes. Exemple:
CREATE TABLE table1 (toto int, bar int); CREATE UNIQUE INDEX ux_table1_foo ON table1 (toto); - Créer un index unique sur foo. INSERT INTO table1 (foo, bar) VALUES (1, 2); - OK INSERT INTO table1 (foo, bar) VALUES (2, 2); - OK INSERT INTO table1 (foo, bar) VALUES (3, 1); - OK INSERT INTO table1 (foo, bar) VALUES (1, 4); - Échec! Entrée en double '1' pour la clé 'ux_table1_foo'
La dernière insertion échoue car elle ne respecte pas l'index unique de la colonne foo
lorsqu'elle tente d'insérer la valeur 1 dans cette colonne une seconde fois.
Dans MySQL, une contrainte unique autorise plusieurs NULL.
Il est possible de créer un index unique sur plusieurs colonnes.
Clé primaire versus index unique
Les choses qui sont les mêmes:
Des choses différentes:
Vous pouvez le voir comme ça:
ne clé primaire IS Unique
ne valeur unique ne doit pas nécessairement être la représentation de l'élément
Sens?; Une clé primaire est utilisée pour identifier l'élément. Si vous avez une "personne", vous souhaitez avoir un numéro d'identification personnel (SSN ou autre) qui est principal pour votre personne.
D'autre part, la personne peut avoir un courrier électronique unique, mais ne l'identifie pas.
J'ai toujours des clés primaires, même dans les tables de relations (la table intermédiaire/table de connexion) que je pourrais avoir. Pourquoi? J'aime bien suivre une norme lors du codage, si la "personne" a un identifiant, la voiture a un identifiant, alors, la personne -> voiture devrait aussi avoir un identifiant!
Les clés étrangères fonctionnent avec des contraintes uniques ainsi que des clés primaires. De la documentation en ligne:
Une contrainte FOREIGN KEY ne doit pas nécessairement être liée à une contrainte PRIMARY KEY dans une autre table; il peut également être défini pour référencer les colonnes d'une contrainte UNIQUE dans une autre table
Pour la réplication transactionnelle, vous avez besoin de la clé primaire. De la documentation en ligne:
Les tables publiées pour la réplication transactionnelle doivent avoir une clé primaire. Si une table se trouve dans une publication de réplication transactionnelle, vous ne pouvez pas désactiver les index associés aux colonnes de clé primaire. Ces index sont requis par la réplication. Pour désactiver un index, vous devez d'abord supprimer la table de la publication.
Les deux réponses sont pour SQL Server 2005.
Le choix du moment d'utilisation d'une clé primaire de substitution, par opposition à une clé naturelle, est délicat. Des réponses telles que, toujours ou jamais, sont rarement utiles. Je trouve que cela dépend de la situation.
A titre d'exemple, j'ai les tableaux suivants:
CREATE TABLE toll_booths (
id INTEGER NOT NULL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
...
UNIQUE(name)
)
CREATE TABLE cars (
vin VARCHAR(17) NOT NULL PRIMARY KEY,
license_plate VARCHAR(10) NOT NULL,
...
UNIQUE(license_plate)
)
CREATE TABLE drive_through (
id INTEGER NOT NULL PRIMARY KEY,
toll_booth_id INTEGER NOT NULL REFERENCES toll_booths(id),
vin VARCHAR(17) NOT NULL REFERENCES cars(vin),
at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
amount NUMERIC(10,4) NOT NULL,
...
UNIQUE(toll_booth_id, vin)
)
Nous avons deux tables d'entités (toll_booths
et cars
) et une table de transaction (drive_through
). Le toll_booth
table utilise une clé de substitution car elle ne possède aucun attribut naturel dont le changement ne peut pas être garanti (le nom peut être facilement modifié). La table cars
utilise une clé primaire naturelle car son identifiant unique ne change pas (vin
). Le drive_through
table de transaction utilise une clé de substitution pour une identification facile, mais a également une contrainte unique sur les attributs qui sont garantis comme étant uniques au moment où l'enregistrement est inséré.
http://database-programmer.blogspot.com a d'excellents articles sur ce sujet particulier.
Les clés primaires ne présentent aucun inconvénient.
Pour ajouter seulement quelques informations aux réponses @MrWiggles et @Peter Parker, lorsque la table n'a pas de clé primaire, par exemple, vous ne pourrez pas éditer les données dans certaines applications clé primaire). Postgresql permet à plusieurs valeurs NULL d'être dans la colonne UNIQUE, PRIMARY KEY n'autorise pas les valeurs NULL. De plus, certains ORM générant du code peuvent avoir des problèmes avec des tables sans clé primaire.
MISE À JOUR:
Autant que je sache, il n'est pas possible de répliquer des tables sans clé primaire dans MSSQL, du moins sans problèmes ( détails ).
Il n’existe pas de clé primaire en théorie des données relationnelles, il faut donc répondre à votre question au niveau pratique.
Les index uniques ne font pas partie du standard SQL. L'implémentation particulière d'un SGBD déterminera les conséquences de la déclaration d'un index unique.
Dans Oracle, la déclaration d'une clé primaire entraîne la création d'un index unique en votre nom. La question est donc pratiquement sans objet. Je ne peux pas vous parler d'autres produits de SGBD.
Je préfère déclarer une clé primaire. Cela a pour effet d'interdire les valeurs NULL dans la ou les colonnes de clé, ainsi que les doublons. Je suis également favorable à la déclaration des contraintes REFERENCES pour appliquer l'intégrité de l'entité. Dans de nombreux cas, la déclaration d’un index sur le ou les moyens d’une clé étrangère accélère les jointures. Ce type d’index ne devrait en général pas être unique.
Si quelque chose est une clé primaire, en fonction de votre moteur de base de données, la table entière est triée en fonction de la clé primaire. Cela signifie que les recherches sont beaucoup plus rapides sur la clé primaire, car elle n’a pas à effectuer de déréférencement, mais plutôt à tout autre type d’index. En plus de cela, c'est juste de la théorie.
Tant que vous n'autorisez pas NULL pour une valeur, elles doivent être traitées de la même manière, mais la valeur NULL est gérée différemment sur les bases de données (AFAIK MS-SQL n'autorisant pas plus d'une (1) valeur NULL, mySQL et Oracle le permettent , si une colonne est UNIQUE) Donc vous devez définir cette colonne NOT NULL UNIQUE INDEX
En plus de ce que les autres réponses ont dit, certaines bases de données et systèmes peuvent obliger un primaire pour être présent. Une situation vient à l'esprit; Lors de l'utilisation de la réplication d'entreprise avec Informix, un PC doit être présent pour qu'une table puisse participer à la réplication.
D'après ce que je comprends, une clé primaire et un index unique avec une contrainte non nulle sont identiques (*); et je suppose que l’un choisit l’un ou l’autre en fonction de ce que la spécification énonce ou implique explicitement (une question de ce que vous voulez exprimer et appliquer explicitement). S'il requiert l'unicité et la valeur null, faites-en une clé primaire. Si cela se produit, toutes les parties d'un index unique ne sont pas nulles sans que cela soit nécessaire, faites-en simplement un index unique.
La seule différence qui reste est que vous pouvez avoir plusieurs index uniques non null, alors que vous ne pouvez pas avoir plusieurs clés primaires.
(*) Sauf différence pratique: une clé primaire peut être la clé unique par défaut pour certaines opérations, comme la définition d'une clé étrangère. Ex. si l'on définit une clé étrangère faisant référence à une table et ne fournit pas le nom de la colonne, si la table référencée a une clé primaire, la clé primaire sera alors la colonne référencée. Sinon, la colonne référencée devra être nommée explicitement.
D'autres ici ont mentionné la réplication de base de données, mais je ne le sais pas.
Il existe certains inconvénients entre les INDEX CLUSTERED et les INDEX UNIQUES.
Comme déjà indiqué, un INDEX CLUSTERÉ ordonne physiquement les données de la table.
Cela signifie que lorsque vous avez beaucoup d'insertions ou de suppressions sur une table contenant un index clusterisé, vous modifiez les données à chaque fois (enfin, presque, en fonction de votre facteur de remplissage), la table physique doit être mise à jour pour rester triée.
Cela convient très bien dans les petites tables relatives, mais vous obtiendrez des problèmes lorsque vous obtiendrez des tables contenant beaucoup de données en Go, ainsi que des insertions/suppressions affectant le tri.
Je ne crée presque jamais une table sans clé primaire numérique. S'il existe également une clé naturelle qui devrait être unique, je lui mets également un index unique. Les jointures sont plus rapides sur les entiers que les clés naturelles multicolonnes, les données ne doivent être modifiées qu’à un seul endroit (les clés naturelles ont tendance à être mises à jour, ce qui est une mauvaise chose quand il s’agit de relations de clé primaire - clé étrangère). Si vous avez besoin d’une réplication, utilisez un GUID au lieu d’un entier, mais je préfère la plupart du temps une clé lisible par l’utilisateur, en particulier si elle a besoin de la voir pour faire la distinction entre John Smith et John Smith.
Les rares fois où je ne crée pas de clé de substitution surviennent lorsque ma table de jointure est impliquée dans une relation plusieurs à plusieurs. Dans ce cas, je déclare les deux champs comme clé primaire.
Unique Index peut avoir une valeur NULL. Cela crée un INDEX NON CLUSTERÉ. La clé primaire ne peut pas contenir la valeur NULL. Cela crée un INDEX CLUSTERED.
Dans MSSQL, les clés primaires devraient augmenter de façon monotone pour optimiser les performances de l'index en cluster. Par conséquent, un entier avec insert d'identité est préférable à toute clé naturelle qui pourrait ne pas augmenter de façon monotone.