405 votes

Une clé étrangère peut-elle être NULL et/ou dupliquée ?

Veuillez clarifier deux choses pour moi :

  1. Une clé étrangère peut-elle être NULL ?
  2. Une clé étrangère peut-elle être dupliquée ?

Pour autant que je sache, NULL ne devrait pas être utilisé dans les clés étrangères, mais dans une de mes applications, je suis capable de saisir NULL à la fois dans Oracle et dans SQL Server, et je ne sais pas pourquoi.

1 votes

@Adrian : A ma connaissance, la clé étrangère ne peut pas être nulle mais elle prend la valeur nulle dans sql server et oracle. pouvez-vous expliquer pourquoi ?

0 votes

@Jams - lisez le lien dans ma réponse.

12 votes

Cela ne peut être supprimé car les réponses et la question sont utiles. N'hésitez pas à modifier la question pour l'améliorer.

649voto

HLGEM Points 54641

Réponse courte : Oui, il peut s'agir de NULL ou de duplicata.

Je veux expliquer pourquoi une clé étrangère peut avoir besoin d'être nulle ou doit être unique ou non unique. Tout d'abord, rappelez-vous qu'une clé étrangère exige simplement que la valeur de ce champ existe d'abord dans une autre table (la table parente). C'est tout ce qu'une clé étrangère est par définition. Par définition, une valeur nulle n'est pas une valeur. Nul signifie que nous ne savons pas encore quelle est la valeur.

Laissez-moi vous donner un exemple concret. Supposons que vous ayez une base de données qui stocke des propositions de vente. Supposons en outre que chaque proposition n'ait qu'un seul commercial affecté et un seul client. Votre table de propositions aurait donc deux clés étrangères, l'une avec l'ID du client et l'autre avec l'ID du représentant commercial. Cependant, au moment de la création de l'enregistrement, un représentant n'est pas toujours affecté (parce que personne n'est encore libre de travailler dessus), de sorte que l'ID du client est renseigné mais que l'ID du représentant peut être nul. En d'autres termes, vous avez généralement besoin de la possibilité d'avoir un FK nul lorsque vous ne connaissez pas sa valeur au moment de la saisie des données, mais que vous connaissez d'autres valeurs de la table qui doivent être saisies. Pour autoriser les valeurs nulles dans un FK, il suffit généralement d'autoriser les valeurs nulles dans le champ qui possède le FK. La valeur nulle est distincte de l'idée qu'il s'agit d'un FK.

Le fait qu'elle soit unique ou non dépend de la relation entre la table et la table parente, qu'elle soit unique ou non. Maintenant, si vous avez une relation un à un, il est possible d'avoir toutes les données dans une seule table, mais si la table devient trop large ou si les données sont sur un sujet différent (l'employé - l'exemple d'assurance donné par @tbone par exemple), alors vous voulez des tables séparées avec un FK. Vous voudrez alors faire en sorte que ce FK soit également le PK (qui garantit l'unicité) ou lui appliquer une contrainte unique.

La plupart des FK sont destinés à une relation d'un à plusieurs et c'est ce que vous obtenez d'un FK sans ajouter une contrainte supplémentaire sur le champ. Vous avez donc une table de commande et une table de détails de la commande, par exemple. Si le client commande dix articles en une seule fois, il a une commande et dix enregistrements de détails de la commande qui contiennent le même ID de commande que le FK.

18 votes

Donc c'est censé être mieux que d'avoir un faux vendeur nommé "Non attribué" ?

8 votes

Un commentaire. Les nuls laissent beaucoup de place aux erreurs dans les requêtes des personnes qui ne savent pas comment SQL gère (mal) 3VL. Si un vendeur n'est vraiment pas nécessaire pour une certaine table R, il suffit de ne pas inclure cet enregistrement. Une table séparée peut être "ProposalAssignedTo" ou autre, avec les contraintes appropriées. Un auteur de requête peut alors joindre cette table, et fournir sa propre logique pour ce que nous voulons faire quand une proposition n'a pas de vendeur. NULL ne signifie pas seulement "nous ne savons pas" - il peut être utilisé pour beaucoup de choses (c'est pourquoi c'est presque toujours une mauvaise idée).

31 votes

@nWest, je ne permets pas aux personnes incompétentes d'interroger mes bases de données et tout développeur qui ne sait pas comment gérer les nuls est incompétent. Il arrive que les données ne soient pas connues au moment de la saisie initiale d'un champ particulier, mais que les autres champs soient nécessaires à ce moment-là.

51voto

JNK Points 32743

1 - Oui, depuis au moins SQL Server 2000.

2 - Oui, tant qu'il ne s'agit pas d'un UNIQUE ou lié à un index unique.

1 votes

Ce lien est mort.

51voto

tbone Points 7147

De la bouche du cheval :

Les clés étrangères permettent des valeurs de clé qui sont toutes NULL, même s'il n'y a pas de clé PRIMAIRE ou UNIQUE correspondante. clés PRIMAIRES ou UNIQUES correspondantes

Aucune contrainte sur la clé étrangère

Lorsqu'aucune autre contrainte n'est définie sur la clé étrangère, un nombre quelconque de lignes de la table enfant peut faire référence à la même valeur de clé parentale. de lignes de la table enfant peuvent faire référence à la même valeur de clé parentale. Ce modèle autorise les valeurs nulles dans la clé étrangère. ...

Contrainte NOT NULL sur la clé étrangère

Lorsque les valeurs nulles ne sont pas autorisées dans dans une clé étrangère, chaque ligne de la table enfant doit faire explicitement référence à une valeur de la clé parent. valeur de la clé parentale, car les valeurs nulles ne sont pas autorisées dans la clé étrangère. étrangère.

Un nombre quelconque de lignes de la table enfant peut faire référence à la même valeur de clé parentale. parent, ce modèle établit donc une relation de type "one-to-many" (un à plusieurs) entre les clés parentales et étrangères. Cependant, chaque ligne de la table enfant doit faire référence à une valeur de clé parentale ; l'absence d'une valeur (un null) dans la clé étrangère ne doit pas être un problème. (un null) dans la clé étrangère n'est pas autorisée. Le même exemple de la section précédente peut être utilisé pour illustrer une telle relation. Toutefois, dans ce cas, les employés doivent faire référence à un département spécifique. département.

Contrainte UNIQUE sur la clé étrangère

Lorsqu'une contrainte UNIQUE est définie sur la clé étrangère, une seule ligne de la table enfant peut faire référencer une valeur de clé parentale donnée. Ce modèle autorise les valeurs nulles dans la clé étrangère.

Ce modèle établit une relation biunivoque entre les clés parentales et étrangères. et les clés étrangères qui autorise des valeurs indéterminées (nulles) dans la clé étrangère clé étrangère. Par exemple, supposons que la table employee possède une colonne nommée MEMBERNO, qui fait référence à un numéro d'adhésion de l'employé à la d'assurance de l'entreprise. De plus, une table nommée INSURANCE possède une clé primaire nommée MEMBERNO et d'autres clés étrangères. primaire nommée MEMBERNO, et d'autres colonnes de la table conservent les informations respectives informations relatives à la police d'assurance d'un employé. Le MEMBERNO de la table la table des employés doit être à la fois une clé étrangère et une clé unique :

  • Pour appliquer les règles d'intégrité référentielle entre les tables EMP_TAB et INSURANCE (la contrainte FOREIGN KEY).

  • Pour garantir que chaque employé possède un numéro de membre unique (la contrainte de clé contrainte de clé UNIQUE)

Contraintes UNIQUE et NOT NULL sur la clé étrangère

Lorsque les contraintes UNIQUE et NOT NULL sont définies sur la clé étrangère, une seule ligne de la table enfant dans la table enfant peut faire référence à une valeur de clé parentale donnée, et parce que les valeurs les valeurs NULL ne sont pas autorisées dans la clé étrangère, chaque ligne de la table doit faire explicitement référence à une valeur de la clé parentale.

Regardez ça :

Lien vers Oracle 11g

23voto

Oui, la clé étrangère peut être nulle, comme l'ont dit les programmeurs expérimentés... Je voudrais ajouter un autre scénario où la clé étrangère devra être nulle.... Supposons que nous avons des tables commentaires, Images et Vidéos dans une application qui permet des commentaires sur les images et les vidéos. Dans la table commentaires, nous pouvons avoir deux clés étrangères PicturesId, et VideosId avec la clé primaire CommentId. Ainsi, lorsque vous commentez une vidéo, seul VideosId sera requis et pictureId sera nul... et si vous commentez une image, seul PictureId sera requis et VideosId sera nul...

1 votes

Je pense qu'il existe une meilleure façon de résoudre ce problème. Plutôt que de créer de nouvelles colonnes, vous pouvez avoir deux colonnes, à savoir "id" et "type", qui contiendront l'id et le nom de la table de la clé étrangère. Par exemple, id=1, type=Picture représentera le lien vers la table Picture avec l'id 1. L'avantage de cette solution est que vous n'aurez pas à créer de nouvelles colonnes lorsque des commentaires seront ajoutés à des tables supplémentaires. L'inconvénient est qu'il n'y aura pas de contrainte de clé étrangère au niveau de la base de données, la contrainte devra plutôt être au niveau de l'application.

8 votes

@Agent : Nous avons eu cette "solution" en utilisation de production. Ne le faites pas, c'est terrible. Faire des requêtes devient ce désordre de, "si c'est le type 1, joindre à cette table, sinon joindre à ceci". C'était un cauchemar pour nous. Nous avons fini par faire ce que dit cette réponse et avons créé une nouvelle colonne pour chaque type de jointure. La création de colonnes est bon marché. Son seul défaut est que beaucoup de colonnes rendent Toad difficile à utiliser, mais c'est juste un défaut de Toad.

1 votes

@FighterJet Rails fournit un excellent cadre ORM qui gère même les requêtes complexes avec cette solution.

14voto

shinxg Points 162

cela dépend du rôle que cette foreign key joue dans votre relation.

  1. si cela foreign key est également un key attribute dans votre relation, alors il ne peut s'agir de NULL
  2. si cela foreign key est un attribut normal dans votre relation, alors il peut être NULL.

3 votes

Que voulez-vous dire par key attribute ?

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