Vissa mycket bra designers använder NULLs i främmande nycklar utan negativa konsekvenser. Själv lutar jag åt det. En nullbar FK representerar ett valfritt förhållande. I fall där entiteten inte har någon relation innehåller FK en NULL. Utrymmet ovanför är minimalt. När joins (equijoins, mer exakt) görs över de två tabellerna, kommer instanser som innehåller NULL i FK att falla ur joinen, och det är lämpligt.
Med det sagt kommer jag att rekommendera dig en fjärde metod. Detta involverar totalt fyra tabeller, konton, widgets, typer och anpassade_typer. Tabellen custom_types använder en teknik som kallas Shared-primary-key, som beskrivs nedan.
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)
);
Kolumnen type_id i custom_types är en delad primärnyckel. Lägg märke till att den deklareras BÅDE som en primärnyckel och som en främmande nyckel, och att den inte använder autonumrering. Det är en kopia av primärnyckeln i typer för motsvarande post. Tabellen anpassade typer innehåller all data som finns i anpassade typer men som saknas i förinställda typer.
För förinställda typer görs en inmatning i typer, men ingen inmatning i custom_types. För custom_types görs först en inmatning i typer, och sedan kopieras det resulterande värdet av type_id över till custom_types, tillsammans med account_id.
Om du INNER JOIN-typer och custom_types, faller de förinställda typerna ur kopplingen. Om du vill ha både anpassade och förinställda typer i en enda join måste du använda en LEFT JOIN eller en RIGHT JOIN för att få den effekten. Observera att resultatet av en LEFT eller RIGHT JOIN kommer att innehålla några NULL, även om dessa NULLs inte är lagrade i databasen.
Klicka på denna shared-primary-key ger dig en mer detaljerad beskrivning av tekniken med delad primärnyckel.