web-dev-qa-db-fra.com

en général, chaque table d'une base de données doit-elle avoir un champ d'identité à utiliser comme PK?

Cela semble être un double même si je le demande, mais j'ai cherché et je ne l'ai pas trouvé. Cela semble être une bonne question pour SO - même si je suis sûr que je peux le trouver sur de nombreux blogs, etc. là-bas. SO en aura plus d'un débat que vous pouvez obtenir sur un blog.

Je rencontre un problème avec une jointure: récupérer trop d'enregistrements. Je pense à cela comme une "expansion". J'ai ajouté une table à l'ensemble des jointures et le nombre de lignes a augmenté, beaucoup trop. Habituellement, lorsque cela se produit, j'ajoute une sélection de tous les champs ID impliqués dans la jointure. De cette façon, il est assez évident où l'expansion se produit et je peux changer le ON de la jointure pour le corriger. Sauf dans ce cas, la table que j'ai ajoutée n'a pas de champ ID. Pour moi, c'est un problème. Mais je me trompe peut-être.

La question: chaque table d'une base de données doit-elle avoir un champ IDENTITY utilisé comme PK? Y a-t-il des inconvénients à avoir un champ ID dans chaque table? Et si vous êtes raisonnablement sûr que ce tableau ne sera jamais utilisé dans une relation PK/FK?

Liés, mais pas en double: Quand avoir une colonne d'identité n'est pas une bonne idée?

Apparemment, ce débat a été en cours depuis un certain temps . Shoulda su.

Ce message (substitut vs clés naturelles) est également pertinent.

43
jcollum

Il existe deux concepts proches mais à ne pas confondre: IDENTITY et PRIMARY KEY

Chaque table (à l'exception des rares conditions) doit avoir un PRIMARY KEY, c'est-à-dire une valeur ou un ensemble de valeurs qui identifient de manière unique une ligne.

Voir ici pour savoir pourquoi.

IDENTITY est une propriété d'une colonne dans SQL Server ce qui signifie que la colonne sera remplie automatiquement avec des valeurs d'incrémentation.

En raison de la nature de cette propriété, les valeurs de cette colonne sont intrinsèquement UNIQUE.

Cependant, aucune contrainte UNIQUE ou index UNIQUE n'est automatiquement créé sur la colonne IDENTITY et après avoir émis SET IDENTITY_INSERT ON il est possible d'insérer des valeurs en double dans une colonne IDENTITY, sauf si cela avait été explicitement contraint UNIQUE.

La colonne IDENTITY ne doit pas nécessairement être un PRIMARY KEY, mais le plus souvent, il est utilisé pour remplir le substitut PRIMARY KEYs

Il peut être utile ou non dans un cas particulier.

Par conséquent, la réponse à votre question:

La question: chaque table d'une base de données doit-elle avoir un champ IDENTITY utilisé comme PK?

est-ce:

Non. Dans certains cas, une table de base de données ne doit PAS avoir un champ IDENTITY comme PRIMARY KEY.

Trois cas me viennent à l'esprit quand ce n'est pas la meilleure idée d'avoir un IDENTITY comme PRIMARY KEY:

  • Si ton PRIMARY KEY est composite (comme dans les tables de liens plusieurs-à-plusieurs)
  • Si ton PRIMARY KEY est naturel (comme un code d'état)
  • Si ton PRIMARY KEY doit être unique dans toutes les bases de données (dans ce cas, vous utilisez GUID/UUID/NEWID)

Tous ces cas impliquent la condition suivante:

Vous ne devriez pas avoir IDENTITY lorsque vous vous souciez des valeurs de votre PRIMARY KEY et les insérer explicitement dans votre table.

Mise à jour:

Les tables de liens plusieurs à plusieurs doivent avoir la paire de id à la table qu'ils lient en tant que clé composite.

C'est une clé composite naturelle que vous devez déjà utiliser (et faire UNIQUE), il n'y a donc aucun intérêt à générer une clé de substitution pour cela.

Je ne vois pas pourquoi voudriez-vous référencer un many-to-many lier la table de toute autre table à l'exception des tables qu'ils lient, mais supposons que vous ayez un tel besoin.

Dans ce cas, vous référencez simplement la table de liens par la clé composite.

Cette requête:

CREATE TABLE a (id, data)
CREATE TABLE b (id, data)
CREATE TABLE ab (a_id, b_id, PRIMARY KEY (a_id, b_id))
CREATE TABLE business_rule (id, a_id, b_id, FOREIGN KEY (a_id, b_id) REFERENCES ab)

SELECT  *
FROM    business_rule br
JOIN    a
ON      a.id = br.a_id

est beaucoup plus efficace que celui-ci:

CREATE TABLE a (id, data)
CREATE TABLE b (id, data)
CREATE TABLE ab (id, a_id, b_id, PRIMARY KEY (id), UNIQUE KEY (a_id, b_id))
CREATE TABLE business_rule (id, ab_id, FOREIGN KEY (ab_id) REFERENCES ab)

SELECT  *
FROM    business_rule br
JOIN    a_to_b ab
ON      br.ab_id = ab.id
JOIN    a
ON      a.id = ab.a_id

, pour des raisons évidentes.

61
Quassnoi

Presque toujours oui. Par défaut, j'inclus généralement un champ d'identité, sauf s'il existe une raison impérieuse de ne pas le faire. Je rencontre rarement de telles raisons, et le coût du champ d'identité est minime, donc généralement j'inclus.

La seule chose à laquelle je puisse penser du haut de ma tête, où je ne l'ai pas été, était une base de données hautement spécialisée qui était davantage utilisée comme banque de données qu'une base de données relationnelle où le SGBD était utilisé pour presque toutes les fonctionnalités, à l'exception d'une modélisation relationnelle importante. (Il s'agissait d'un tampon de données à volume élevé et à taux de rotation élevé.)

14
Greg D

Je suis fermement convaincu que les clés naturelles sont souvent bien pires que les clés artificielles, car vous n'avez souvent aucun contrôle sur leur modification, ce qui peut entraîner d'intenses problèmes d'intégrité des données ou de performances.

Cependant, il y a quelques (très peu) de clés naturelles qui ont du sens sans être un champ d'identité (l'abréviation d'état à deux lettres vient à l'esprit, il est extrêmement rare que ces abréviations de type officiel changent.)

Toute table qui est une table de jointure pour modéliser une relation plusieurs à plusieurs n'a probablement pas besoin non plus d'un champ d'identité supplémentaire. Faire les deux champs clés ensemble la clé primaire fonctionnera très bien.

En dehors de cela, j'ajouterais, en général, un champ d'identité à la plupart des autres tables, sauf indication contraire dans ce cas particulier. C'est une mauvaise pratique de ne pas créer une clé primaire sur une table ou si vous utilisez des clés de substitution pour ne pas placer un index unique sur les autres champs nécessaires pour garantir l'unicité dans la mesure du possible (sauf si vous aimez vraiment résoudre les doublons).

12
HLGEM

Chaque table doit avoir un ensemble de champs qui l'identifient de manière unique. La présence ou non d'un champ d'identifiant numérique distinct des champs de données dépend du domaine que vous essayez de modéliser. Toutes les données ne tombent pas facilement dans le paradigme du "numéro d'identification unique", et en tant que tel, il serait inapproprié de les forcer. Étant donné que, beaucoup de données s'intègrent facilement dans ce paradigme et, à ce titre, nécessiteraient un tel identifiant. Il n'y a pas de réponse unique pour toujours faire X dans n'importe quel environnement de programmation, et ceci est un autre exemple.

4
Mark Roddy

Non. Chaque fois que vous avez une table avec une colonne d'identité artificielle, vous devez également identifier la clé primaire naturelle de la table et vous assurer qu'il existe également une contrainte unique sur cet ensemble de colonnes afin de ne pas obtenir deux lignes qui sont identique en dehors de la colonne d'identité vide de sens par accident.

L'ajout d'une colonne d'identité n'est pas gratuit. Il y a un surcoût dans l'ajout d'une colonne d'identité inutile à une table - généralement 4 octets par ligne de stockage pour la valeur d'identité, plus un index supplémentaire entier (qui pèsera probablement entre 8 et 12 octets par ligne plus le surcoût). Il faut également un peu de temps pour élaborer le plan de requête le plus rentable car il existe un index supplémentaire par table. Certes, si la table est petite et la machine grande, ce surcoût n'est pas critique - mais pour les plus gros systèmes, c'est important.

4
Jonathan Leffler

Si vous avez modélisé, conçu, normalisé, etc., vous n'aurez pas de colonnes d'identité.

Vous aurez identifié des clés naturelles et candidates pour vos tables.

Vous pouvez décider d'une clé de substitution en raison de l'architecture physique (par exemple étroite, numérique, strictement monotone), par exemple, car l'utilisation d'une colonne nvarchar (100) n'est pas une bonne idée (il faut toujours une contrainte unique).

Ou à cause de l'idéologie: ils font appel à OO développeurs que j'ai trouvés.

Ok, supposons que les colonnes ID. Au fur et à mesure que votre base de données devient plus complexe, disons plusieurs couches, comment pouvez-vous joner directement des tables parent et grand-enfant. Vous ne pouvez pas: vous avez toujours besoin de tables intermédiaires et de colonnes PK-FL bien indexées. Avec une clé composite, tout est là pour vous ...

Ne vous méprenez pas: je les utilise. Mais je sais pourquoi je les utilise ...

Éditer:

Je serais intéressé à rassembler les correspondances "toujours ID" + "pas de procs stockés" d'une part, avec "utiliser les procs stockés" + "ID lorsqu'ils en bénéficient" de l'autre ...

3
gbn

Reconnaître la distinction entre un champ d'identité et une clé ... Chaque table doit avoir une clé, pour éliminer la corruption de données de la saisie par inadvertance de plusieurs lignes qui représentent la même "entité". Si la seule clé d'une table est une clé de substitution vide de sens, cette fonction est effectivement manquante.

otoh, aucune table n'a besoin d'une identité, et certainement pas toutes les tables en bénéficient ... Les exemples sont: une table avec une clé courte et fonctionnelle, une table qui n'a pas d'autre table la référençant via une clé étrangère, ou une table qui est dans une relation de un à zéro ou un avec une autre table ... aucune de celles-ci n'a besoin d'une identité

1
Charles Bretana

Je ne peux penser à aucun inconvénient d'avoir un champ ID dans chaque table. Le fait de fournir le type de votre champ ID fournit suffisamment d'espace pour que votre table se développe.

Cependant, vous n'avez pas nécessairement besoin d'un seul champ pour garantir l'identité de vos lignes. Donc non, un le champ ID unique n'est pas obligatoire.

Primaire et étranger Clés peut se composer non seulement d'un seul champ, mais de plusieurs champs. Ceci est typique pour les tables implémentant une relation N-N.

Vous pouvez parfaitement avoir PRIMARY KEY (fa, fb) sur votre table:

CREATE TABLE t(fa INT , fb INT);
ALTER TABLE t ADD PRIMARY KEY(fa , fb);
1
jeje

Oui, pour la grande majorité des cas.

Les cas de bord ou les exceptions peuvent être des choses comme:

  • tables de jointure bidirectionnelles pour modéliser les relations m: n
  • tables temporaires utilisées pour l'insertion en masse d'énormes quantités de données

Mais à part cela, je pense qu'il n'y a aucune bonne raison de ne pas avoir une clé primaire pour identifier de manière unique chaque ligne d'une table, et à mon avis, utiliser un champ IDENTITY est l'un des meilleurs choix (je préfère les clés de substitution aux clés naturelles - ils sont plus fiables, stables, ne changent jamais, etc.).

Marc

1
marc_s

Je dirais que si vous pouvez trouver une clé simple et naturelle dans votre table (c'est-à-dire une colonne), utilisez-la comme clé au lieu d'une colonne d'identité.

Je donne généralement à chaque table une sorte d'identifiant unique, qu'il soit naturel ou généré, car alors je suis garanti que chaque ligne est identifiée de manière unique.

Personnellement, j'évite les colonnes IDENTITY (incrémentation d'identité, comme 1, 2, 3, 4) comme la peste. Ils causent beaucoup de tracas, surtout si vous supprimez des lignes de cette table. J'utilise à la place des identificateurs uniques générés s'il n'y a pas de clé naturelle dans la table.

Quoi qu'il en soit, aucune idée si c'est la pratique acceptée, cela me semble juste. YMMV.

0
Matthew Jones