Някои много добри дизайнери използват NULL във външни ключове без неблагоприятни последици. Аз самият се клоня по този начин. FK с нулева стойност представлява незадължителна връзка. В случаи, когато обектът няма връзка, FK съдържа NULL. Пространството над главата е минимално. Когато свързванията (по-точно equijoins) се извършват в двете таблици, екземпляри, съдържащи NULL във FK, ще отпаднат от обединението и това е подходящо.
След като казах това, ще ви препоръчам четвърти метод. Това включва общо 4 таблици, акаунти, джаджи, типове и custom_types. Таблицата custom_types използва техника, наречена Shared-primary-key, описана по-долу.
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)
);
Колоната type_id в custom_types е споделен първичен ключ. Забележете, че той е деклариран И като първичен ключ, и като външен ключ и че не използва автономер. Това е копие на първичния ключ в типове за съответния запис. Таблицата с персонализирани типове съдържа всички данни, които присъстват в персонализираните типове, но липсват в предварително зададените типове.
За предварително зададени типове запис се прави в типове, но не се прави запис в custom_types. За custom_types първо се прави запис в типове, а след това получената стойност на type_id се копира в custom_types, заедно с account_id.
Ако използвате типове INNER JOIN и custom_types, предварително зададените типове отпадат от присъединяването. Ако искате както персонализирани, така и предварително зададени типове в едно свързване, трябва да използвате LEFT JOIN или RIGHT JOIN, за да получите този ефект. Обърнете внимание, че резултатът от LEFT или RIGHT JOIN ще съдържа някои NULL числа, въпреки че тези NULL не се съхраняват в базата данни.
Кликването върху този shared-primary-key ще ви даде по-подробно описание на техниката на споделения първичен ключ.