web-dev-qa-db-fra.com

La clé étrangère peut-elle être nulle?

Dans notre projet de base de données, nous avons une table Sale qui a une clé primaire et deux clés étrangères exclusives: Vehicle_ID et Piece_ID. Par exemple, si nous vendons un véhicule, nous avons besoin de Vehicle_ID comme clé étrangère, mais pas de Piece_ID. Peut-on mettre NULL à Piece_ID, une clé étrangère peut-elle être nulle? Ou est-il possible de faire ce travail?

Merci.

11
notfound90

La colonne (ou les colonnes) d'une clé primaire doit être NOT NULL. Un enregistrement ne peut pas être identifié de manière unique par un NULL. Par conséquent, les colonnes ID situées à l'extrémité référencée de la clé étrangère doivent être définies comme NOT NULL.

Cependant, il est légitime de décider qu'une relation de clé étrangère soit facultative, et le moyen de la représenter consiste à rendre la fin de la référence de la clé facultative, c'est-à-dire autoriser des valeurs NULL.

En termes de modélisation de données, ce que vous avez décrit est un arc (exclusif): "une table ... avec deux ou plusieurs clés étrangères où une et une seule d'entre elles peuvent être non nulles". En modélisation logique, les arcs sont parfaitement acceptables, mais il existe un fort courant d'opinion en faveur de leur mise en œuvre en tant que tableaux séparés. Dans votre scénario, il s'agirait d'une table générique Sale et de deux tables de sous-types, VehicleSale et PieceSale.

Les avantages de la mise en œuvre de la table séparée sont les suivants:

  • plus facile d'appliquer les contraintes de clé étrangère;
  • plus facile d'ajouter des colonnes supplémentaires concernant (par exemple) les ventes de véhicules qui ne s'appliquent pas aux ventes à la pièce;
  • plus facile d'étendre le modèle avec des sous-types supplémentaires;
  • modèle de données plus clair, ce qui peut simplifier le développement d'applications.

Cependant, les avantages ne sont pas tous à sens unique. Bien qu'il soit assez facile de s'assurer qu'une Sale s'applique soit à une VehicleSale, soit à une PieceSale mais pas aux deux, appliquer la règle qui dit que Sale doit avoir un enregistrement enfant devient en réalité assez génial.

Ainsi, le conseil qui prévaut est qu'un arc exclusif se trompe et que c'est généralement un bon conseil. Mais ce n'est pas aussi clair que certains le prétendent.

11
APC

Réponse:

Oui, vous pouvez le faire - rendre les FK eux-mêmes NULL, mais ajoutez un CHECK pour vous assurer que l'un d'entre eux contient une valeur non NULL.

Élaboration:

Un FK peut être NULL, ce qui modélise une relation 1..0: N. En d'autres termes, une ligne "enfant" can (mais ce n'est pas obligatoire) a une ligne "parent".

Une clé étrangère NOT NULL modélise une relation 1: N. En d’autres termes, chaque enfant doit avoir un parent.

Quand un FK est composite1, et au moins un de ses champs est NULL, un mélange de valeurs NULL et non-NULL est traité de manière spéciale:

  • Si FK est MATCH FULL, les valeurs all doivent être NULL ou toutes les valeurs doivent être non NULL et correspondre à une ligne parent.
  • Si FK est MATCH PARTIAL, seules les valeurs non-NULL doivent correspondre à une ligne parent (les valeurs NULL sont ignorées).
  • Si FK est MATCH SIMPLE, toutes les valeurs sont non NULL et doivent correspondre à une ligne parent ou il existe au moins une valeur NULL (auquel cas les non-NULL ne doivent pas nécessairement correspondre).

La plupart des SGBD ont la valeur par défaut MATCH SIMPLE (à l'exception notable de MS Access ) et la plupart ne prennent en charge que la valeur par défaut.


1 Ce que vous n'avez pas ici - en le mentionnant pour être complet.

6
Branko Dimitrijevic

Selon ce que vous entendez par "clés étrangères exclusives", vous pourriez penser à des véhicules et à des pièces en tant que deux sous-classes d'une classe supérieure plus grande, appelez-les articles vendables. 

Si vous utilisez un modèle de conception appelé "héritage de table de classe", vous aurez trois tables, une pour la superclasse et une pour chaque table de sous-classe. Si, en outre, vous utilisez une conception appelée "clé primaire partagée", vous pouvez utiliser la même clé primaire pour les trois tables.

Cela permettrait à votre table Vente d'avoir une seule clé étrangère, Saleable_Item_Id, qui fait référence à la table Saleable_Item ainsi qu'à la table Vehicle ou à la pièce, selon le cas. Cela pourrait fonctionner mieux pour vous que la conception existante.

google "héritage table de classe" et "clé primaire partagée" pour plus de détails.

1
Walter Mitty

Oracle ne devrait pas se plaindre si vous avez une clé étrangère nulle.

Avez-vous rencontré des erreurs?

0
Andrew Walters