164 votes

Ce qui ' s mal avec colonnes nullables en composites clés primaires ?

ORACLE n’autorise pas les valeurs NULL dans une des colonnes qui constituent une clé primaire. Il semble que le même est vrai pour la plupart des autres systèmes « niveau de l’entreprise ».

Dans le même temps, la plupart des systèmes permettent également des contraintes unique sur les colonnes nullables.

Comment se fait-il que des contraintes uniques peuvent avoir des valeurs NULL, mais les clés primaires ne peuvent pas ? Y at-il une raison logique fondamentale pour cela ou est-ce plus d’une limitation technique ?

236voto

Tomalak Points 150423

Les clés primaires sont pour identifier de manière univoque lignes. Ceci est fait en comparant toutes les parties d’une clé à l’entrée. Par définition, NULL ne peuvent pas faire partie d’une comparaison - le résultat d’une telle comparaison serait toujours NULL à nouveau.

Additonally, NULL est autorisée dans une clé étrangère, à l’occasion d’une relation en option. Ce qui lui permet de la pharmacocinétique ainsi cela briserait.

65voto

Tony Andrews Points 67363

Une clé primaire définit un identificateur unique pour chaque ligne dans une table : lorsqu’une table possède une clé primaire, vous avez un moyen garanti de choisir n’importe quelle ligne dans celui-ci.

Une contrainte unique n’identifie pas nécessairement tous les rangs ; Il indique juste que si une ligne a valeurs dans ses colonnes, puis ils doivent être uniques. Ce n’est pas suffisant pour identifier de façon unique chaque ligne, qui est ce que doit faire une clé primaire.

49voto

zxq9 Points 384

Fondamentalement parlant, n'est pas une valeur NULL dans un multi-colonne de clé primaire. Mais en avoir une a des implications le concepteur n'a pas l'intention, c'est pourquoi de nombreux systèmes de jeter une erreur lorsque vous essayez ceci.

Prenons le cas du module/les versions des paquets stockés comme une série de domaines:

CREATE TABLE module
  (name        varchar(20) PRIMARY KEY,
   description text);

CREATE TABLE version
  (module      varchar(20) REFERENCES module,
   major       integer NOT NULL,
   minor       integer DEFAULT 0 NOT NULL,
   patch       integer DEFAULT 0 NOT NULL,
   release     integer DEFAULT 1 NOT NULL,
   ext         varchar(20),
   notes       text NOT NULL,
   PRIMARY KEY (module, major, minor, patch, release, ext));

Les 5 premiers éléments de la clé primaire sont régulièrement définies parties de la version en cours, mais certains paquets ont une extension personnalisé qui n'est généralement pas un nombre entier (comme "rc-foo" ou "vanille" ou "beta" ou que ce soit d'autre, quelqu'un pour qui les quatre champs est insuffisante peut rêver). Si un colis n'est pas une extension, alors elle est NULLE dans le modèle ci-dessus, et aucun mal ne serait fait en laissant les choses de cette façon.

Mais ce qui est NULL? Il est censé représenter un manque d'information, un inconnu. Cela dit, peut-être que cela fait plus de sens:

CREATE TABLE version
  (module      varchar(20) REFERENCES module,
   major       integer NOT NULL,
   minor       integer DEFAULT 0 NOT NULL,
   patch       integer DEFAULT 0 NOT NULL,
   release     integer DEFAULT 1 NOT NULL,
   ext         varchar(20) DEFAULT '' NOT NULL,
   notes       text NOT NULL,
   PRIMARY KEY (module, major, minor, patch, release, ext));

Dans cette version "ext" une partie de la tuple n'est PAS NULLE, mais par défaut est une chaîne vide, qui est sémantiquement (et pratiquement) est différente de NULL. Une valeur NULL est un inconnu, alors qu'une chaîne vide est une volonté délibérée de la définition de "quelque chose de pas être présent". En d'autres termes, "vide" et "null" sont des choses différentes. Son la différence entre "je n'ai pas de valeur ici" et "je ne sais pas ce que la valeur est ici."

Lorsque vous vous inscrivez un paquet qui n'a pas de version de l'extension que vous savez qu'il manque une extension, alors une chaîne vide est en fait la valeur correcte. Un NUL ne serait correcte si vous ne savais pas si elle avait eu une extension ou non. Cette situation est plus facile de traiter avec les systèmes où les valeurs de chaîne sont la norme, car il n'y a aucun moyen de représenter un "vide integer" autre que l'insertion de 0 ou 1, qui sera le vent en cours de déploiement dans toute comparaison faite plus tard (qui a ses propres conséquences).

D'ailleurs, les deux façons sont valables dans Postgres (puisque nous allons discuter de "l'entreprise" RDMBSs), mais les résultats de la comparaison peuvent varier un peu quand vous jetez une valeur NULL dans le mix -- parce que NULL == "ne sait pas" donc tous les résultats d'une comparaison avec une valeur NULL vent jusqu'à être NULLE puisque vous ne pouvez pas savoir quelque chose qui est inconnu. Donc cela peut être une source de bogues subtils lors des opérations de tri, de les comparer, etc. Postgres suppose que vous êtes un adulte et peut prendre cette décision pour vous-même. Oracle et DB2 suppose que vous ne savais pas que vous faisiez quelque chose de stupide et de lever une erreur. C'est généralement la bonne chose, mais pas toujours, vous pouvez effectivement ne pas savoir et avoir une valeur NULL dans certains cas et, partant, une ligne avec un inconnu contre lequel des comparaisons significatives sont impossible est le comportement correct.

Dans tous les cas, vous devez vous efforcer d'éliminer le nombre de champs NULL vous permettre à travers l'ensemble du schéma et doublement quand il s'agit de domaines qui font partie de la clé primaire. Dans la grande majorité des cas, la présence de colonnes NULL est une indication de l'onu-normalisé (par opposition délibérée de-normalisée) schéma de conception et doit être pensé très fort avant d'être accepté.

22voto

Cogsy Points 3150

NULL == NULL-> faux (au moins dans les SGBD)

Si vous ne seriez pas en mesure de récupérer toutes les relations à l’aide d’une valeur NULL même avec des colonnes supplémentaires avec de vraies valeurs.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X