Einige sehr gute Designer verwenden NULLen in Fremdschlüsseln ohne nachteilige Folgen. Ich neige selbst so. Ein nullable FK repräsentiert eine optionale Beziehung. In Fällen, in denen die Entität keine Beziehung hat, enthält der FK eine NULL. Der Platzbedarf ist minimal. Wenn Joins (genauer gesagt Equijoins) über die beiden Tabellen hinweg ausgeführt werden, fallen Instanzen, die NULL im FK enthalten, aus dem Join heraus, und das ist angemessen.
Abgesehen davon werde ich Ihnen eine vierte Methode empfehlen. Dies umfasst insgesamt 4 Tabellen, Konten, Widgets, Typen und benutzerdefinierte_Typen. Die Tabelle custom_types verwendet eine Technik namens Shared-Primary-Key, die unten beschrieben wird.
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)
);
Die Spalte „type_id“ in „custom_types“ ist ein gemeinsam genutzter Primärschlüssel. Beachten Sie, dass er sowohl als Primärschlüssel als auch als Fremdschlüssel deklariert ist und keine automatische Nummerierung verwendet. Es ist eine Kopie des Primärschlüssels in Typen für den entsprechenden Eintrag. Die Tabelle der benutzerdefinierten Typen enthält alle Daten, die in benutzerdefinierten Typen vorhanden sind, in voreingestellten Typen jedoch nicht vorhanden sind.
Bei voreingestellten Typen erfolgt ein Eintrag in types, aber kein Eintrag in custom_types. Für custom_types wird zuerst ein Eintrag in types gemacht und dann wird der resultierende Wert von type_id zusammen mit der account_id in custom_types kopiert.
Wenn Sie INNER JOIN-Typen und custom_types verwenden, fallen die voreingestellten Typen aus dem Join heraus. Wenn Sie sowohl benutzerdefinierte als auch voreingestellte Typen in einem einzigen Join haben möchten, müssen Sie einen LEFT JOIN oder einen RIGHT JOIN verwenden, um diesen Effekt zu erzielen. Beachten Sie, dass das Ergebnis eines LEFT- oder RIGHT JOIN einige NULL-Werte enthält, obwohl diese NULL-Werte nicht in der Datenbank gespeichert sind.
Klicken Sie auf diesen shared-primary-key wird Ihnen eine detailliertere Beschreibung der Shared-Primary-Key-Technik geben.