Mysql
 sql >> Base de données >  >> RDS >> Mysql

Question de conception de base de données sur les clés étrangères nulles et la normalisation

Certains très bons concepteurs utilisent des NULL dans des clés étrangères sans conséquences néfastes. Je penche comme ça moi-même. Un FK acceptant la valeur Null représente une relation facultative. Dans les cas où l'entité n'a pas de relation, le FK contient un NULL. L'espace au-dessus est minime. Lorsque des jointures (équijoins, plus précisément) sont effectuées sur les deux tables, les instances contenant NULL dans le FK seront supprimées de la jointure, et c'est approprié.

Cela dit, je vais vous recommander une quatrième méthode. Cela implique un total de 4 tables, comptes, widgets, types et custom_types. La table custom_types utilise une technique appelée Shared-primary-key, décrite ci-dessous.

CREATE TABLE accounts (
    account_id  INT UNSIGNED AUTO_INCREMENT NOT NULL, 
    # Other Columns...,
    PRIMARY KEY (account_id)
    );  
CREATE TABLE widgets (
    widget_id   INT UNSIGNED AUTO_INCREMENT NOT NULL,
    account_id  INT UNSIGNED NOT NULL, 
    type_id     INT UNSIGNED NOT NULL,
    PRIMARY KEY (widget_id),
    FOREIGN KEY (account_id) REFERENCES accounts(account_id) ON DELETE CASCADE,
    FOREIGN KEY (type_id) REFERENCES types(type_id)
    );  
CREATE TABLE types (
    type_id     INT UNSIGNED AUTO_INCREMENT NOT NULL,
    account_id  INT UNSIGNED NOT NULL, 
    name        VARCHAR(100) NOT NULL,
    PRIMARY KEY (type_id),
    FOREIGN KEY (account_id) REFERENCES accounts(account_id)
CREATE TABLE custom_types (
    type_id     INT NOT NULL,
    account_id  INT UNSIGNED NOT NULL, 
    PRIMARY KEY (type_id),
    FOREIGN KEY (type_id) REFERENCES types(type_id),
    FOREIGN KEY (account_id) REFERENCES accounts(account_id)

);

La colonne type_id dans custom_types est une clé primaire partagée. Notez qu'il est déclaré à la fois comme clé primaire et comme clé étrangère, et qu'il n'utilise pas la numérotation automatique. C'est une copie de la clé primaire dans les types pour l'entrée correspondante. Le tableau des types personnalisés contient toutes les données présentes dans les types personnalisés mais absentes des types prédéfinis.

Pour les types prédéfinis, une entrée est effectuée dans types, mais aucune entrée n'est effectuée dans custom_types. Pour custom_types, une entrée est d'abord effectuée dans types, puis la valeur résultante de type_id est copiée dans custom_types, avec account_id.

Si vous utilisez des types INNER JOIN et custom_types, les types prédéfinis sont supprimés de la jointure. Si vous voulez à la fois des types personnalisés et prédéfinis dans une même jointure, vous devez utiliser une jointure gauche ou droite pour obtenir cet effet. Notez que le résultat d'un LEFT ou RIGHT JOIN contiendra des valeurs NULL, même si ces valeurs NULL ne sont pas stockées dans la base de données.

En cliquant sur cette vous donnera une description plus détaillée de la technique de la clé primaire partagée.