Chaque table devrait-elle avoir une clé primaire de substitution / artificielle à champ unique?

33

Je comprends un avantage des clés de substitution / artificielles en général - elles ne changent pas et cela peut être très pratique. Cela est vrai, qu’il s’agisse d’un seul ou de plusieurs domaines, pour autant qu’ils soient «artificiels».

Cependant, il semble parfois que le fait d’avoir un champ entier auto-incrémenté comme clé primaire de chaque table semble être une question de politique. Est-ce toujours la meilleure idée d'avoir une clé à un seul champ et pourquoi (ou pourquoi pas)?

Pour être clair, cette question ne concerne pas l’art artificiel ou naturel, mais la question de savoir si toutes les clés artificielles doivent être à champ unique.

Jack Douglas
la source
1
voir aussi dba.stackexchange.com/a/112632/1396
Jack Douglas

Réponses:

28

Je vais dire non, pas toujours, mais la plupart du temps oui. .

Voici certaines circonstances dans lesquelles vous n'avez pas besoin de clé de substitution ou de clé artificielle:

  • Tables d'intersection pure . S'il n'y a aucun risque que l'intersection soit la cible d'une clé étrangère et si elle risque peu ou pas d'attirer des attributs indépendants (c'est-à-dire autre chose que FK dans les deux tables parent), vous pouvez vous en tirer avec la combinaison des FK comme PK avec une confiance raisonnable.
  • Tables de recherche avec des clés métier statiques . Si vous disposez d'une
    table de recherche avec une clé unique, fixée de manière externe à votre
    entreprise et qui n'a aucune chance de changer pour quelque
    raison que ce soit, l'utilisation de la clé directement peut vous
    simplifier la tâche. Un exemple pourrait être une liste de
    codes d’états ou de provinces ou une liste de numéros normalisés ANSI, etc.
  • Tableaux contenant des données consolidées à partir de plusieurs sources indépendantes . Si votre système contient de nombreuses sources de données qui doivent être regroupées dans une seule table, par exemple au siège social, il vous faut parfois une clé composée qui inclut la valeur de la clé du système source et un code indiquant son état actuel.

Il existe également des situations dans lesquelles la clé de substitution à nombre entier croissante monotone fidèle n’est pas idéale. Vous pouvez avoir des clés qui sont des substituts alphanumériques. Ceux-ci pourraient inclure:

  • Situations dans lesquelles vous devez fusionner des données provenant de plusieurs sources indépendantes. Pour éviter les conflits de clé, vous pouvez utiliser des GUID au lieu de clés IDENTITY.
  • Situations dans lesquelles vous êtes obligé d'utiliser des représentations de clé non numériques. Disons que vous avez une base de données de plaques d'immatriculation. Votre clé pourrait être la valeur alphanumérique au lieu d’un nombre pur.
  • Situations dans lesquelles des exigences externes vous obligent à appliquer une compression à votre valeur de clé. Au lieu d'utiliser 10 chiffres pour un int32, vous pouvez utiliser six chiffres de base 36.

Pourquoi la plupart du temps oui? La réponse la plus fondamentale à cette question est que c'est du pur enfer si vous devez modifier une valeur de clé primaire sur une table. Étant donné que presque tout ce qu'un utilisateur peut voir ou toucher est susceptible d'une mise à jour à un moment donné, l'utilisation d'une valeur de clé visible invite à un véritable enfer. L'utilisation d'une clé de substitution vous évitera de tomber dans ce piège.

Cela dit, souvenez-vous que YAGNI a toute latitude pour appliquer ce concept. Vous n'avez pas besoin de forcer des tables de code avec des clés IDENTITY dans chaque coin de votre schéma, juste au cas où quelqu'un déciderait que le symbole du genre masculin dans votre table d'employé doit changer de M à X ou quelque chose de stupide.

Joel Brown
la source
"L'utilisation d'une clé de substitution vous évitera de tomber dans ce piège" La question ne porte pas sur la mère porteuse vs naturelle, mais sur les mères porteuses mono-champs vs multi-champs.
Jack Douglas
Comme vous l'avez reconnu dans un commentaire à votre propre réponse, nous sommes "d'accord pour ne pas être d'accord" en termes de prudence dans la conception de bases de données. Compte tenu de votre modification, je n’aurais pas fait la distinction entre les clés de substitution et les clés naturelles; mon deuxième point est donc hors sujet. Mes autres points concernant le moment où l'on pourrait s'écarter de l'approche classique identité / séquence sont toujours valables.
Joel Brown
Comme je peux le voir dans l'historique, je n'ai pas changé la question, mais juste une emphase supplémentaire là où je pensais que cela aiderait les lecteurs à feuilleter
Jack Douglas
12

Non.

Je dirais qu'il y a certainement des cas où les clés à un seul champ sont inférieures aux clés composées, du moins pour les clés étrangères . Cela ne veut pas dire que vous ne devriez pas avoir de clé de substitution à champ unique si vous préférez, mais je préfère personnellement que la clé qui est le plus souvent utilisée comme cible d'une clé étrangère soit appelée clé primaire.

Je vais essayer d’illustrer mon propos dans les exemples suivants, dans lesquels:

  • brand est une marque de voiture, par exemple Ford, Toyota, etc.
  • dealer est un concessionnaire physique lié à une marque (par exemple, un concessionnaire Ford vendant uniquement des Ford)
  • model est le type de voiture, par exemple Ford Focus, Ford Fiesta, etc.
  • stock est le nombre actuel de voitures de parc pour chaque concessionnaire

Si nous créons une clé de substitution à champ unique pour dealeret modelcomme suit:

create table brand( brand_id integer primary key );

create table dealer( dealer_id integer primary key, 
                     brand_id integer references brand )

create table model( model_id integer primary key, 
                    brand_id integer references brand )

create table stock( model_id integer references model, 
                    dealer_id integer references dealer, 
                    quantity integer,
                      primary key(model_id, dealer_id) )

alors il est possible d'insérer une rangée dans stockqui relie une Ford dealerà un modèle "Toyota". Ajouter brand_id references brandà stockne fait qu'aggraver le problème. Par ailleurs, si nous conservons la clé étrangère dans la clé primaire comme suit:

create table brand( brand_id integer primary key );

create table dealer( brand_id integer references brand, 
                     dealer_id integer, 
                       primary key(brand_id, dealer_id) )

create table model( brand_id integer references brand, 
                    model_id integer, 
                      primary key(brand_id, model_id) )

create table stock( brand_id integer, 
                    model_id integer, 
                    dealer_id integer, 
                    quantity integer,
                      primary key(brand_id, model_id, dealer_id),
                      foreign key(brand_id, model_id) references model,
                      foreign key(brand_id, dealer_id) references dealer )

maintenant, la règle selon laquelle les concessionnaires "Ford" ne peuvent stocker que des voitures "Ford" est naturellement appliquée par le modèle.

Notez que dans l'exemple «clés composites», il dealer_idest possible que les préférences soient uniques ou non. Il n’est pas nécessaire qu’il soit unique (c’est-à-dire une clé alternative), mais vous perdez très peu de choses (peut-être un peu d’espace de stockage) et cela peut être très pratique, c’est ainsi que je l’utilise habituellement, par exemple:

create table dealer( brand_id integer references brand, 
                     dealer_id serial unique, 
                       primary key(brand_id, dealer_id) )
Jack Douglas
la source
3
En tenant compte des réserves habituelles concernant des exemples qui ne sont pas nécessairement parfaits sous tous les angles, je dirais que ce type de conception est particulièrement fragile. Bien qu'il soit satisfaisant de trouver un moyen d'utiliser DRI pour appliquer des règles métier, cela réduit également votre capacité à réagir aux changements. Si Toyota achète Ford, ou même si un concessionnaire Ford décide de vendre une Toyota usagée, les règles de votre entreprise régies par le DRI vous donneront mal à l'aise en matière d'entretien.
Joel Brown
1
Donc, "vos règles commerciales pourraient changer". Cela est vrai pour toute règle de gestion et il sera toujours potentiellement difficile à modéliser. On me dit généralement quelles sont les règles commerciales - je ne les décide pas moi-même.
Jack Douglas
1
Voulez-vous dire que DRI ne devrait absolument pas être utilisé pour appliquer des règles métier? N'est-ce pas la seule chose que DRI fait? - Même les clés étrangères simples sont des règles commerciales appliquées par DRI.
Jack Douglas
4
Bien sûr, DRI applique les règles commerciales. Vous devez décider quelles règles vont être appliquées dans le code et lesquelles dans votre schéma. Les modifications de schéma sont presque toujours plus difficiles que les modifications de code. Deux types de règles commerciales peuvent être insérées dans votre modèle de données. On y appartient et on n'en a pas. La nature fondamentale des données qui est importante pour votre entreprise ne change pas beaucoup. La manière spécifique dont vous exploitez ces données est beaucoup plus volatile . Une règle telle que les voitures ont un fabricant appartient au modèle de données. Une règle telle que les concessionnaires ne vendront jamais deux marques de voitures ne le fait pas.
Joel Brown
4
"Les modifications de schéma sont presque toujours plus difficiles que les modifications de code" IMO, l'inverse est vrai. En fait, je suis en désaccord avec pratiquement tout ce que vous venez de dire, mais je doute qu’il soit utile de débattre du tirage au sort avec vous, alors je vais en rester là.
Jack Douglas
12

"ça dépend"

Oui: les champs IDENTITY / AUTONUMBER de substitution sont bons lorsque la clé naturelle est large et non numérique. Remarque: cela suppose la fusion de "PK" et de l'index clusterisé qui se produit par défaut dans SQL Server et Sybase, etc.

Non: plusieurs / plusieurs tables lorsque les 2 clés parent suffisent. Ou lorsque la clé naturelle est courte et de longueur fixe, par exemple un code de devise

Bien sûr, un ORM sans tête (lire: (H) Hibernate) peut outrepasser ces règles ...

Edit: relire la question

Une table plusieurs / plusieurs avec 2 clés parent de substitution aura une PK à plusieurs colonnes.
Cependant, il n'a pas besoin d'une autre colonne de substitution.

Si une table a une clé de substitution (IDENTITY, etc.), il n'est pas nécessaire qu'elle soit composée de plusieurs colonnes.

Vous pouvez avoir une super clé qui inclut le substitut, mais ce serait pour appliquer d'autres règles (par exemple, des sous-types ).

gbn
la source