非常に優れた設計者の中には、外部キーにNULLを使用しても、悪影響はありません。私はそのように身を乗り出します。 null許容FKは、オプションの関係を表します。エンティティに関係がない場合、FKにはNULLが含まれます。スペースのオーバーヘッドは最小限です。 2つのテーブル間で結合(より正確には等結合)が行われると、FKにNULLを含むインスタンスは結合から脱落します。これは適切です。
そうは言っても、私はあなたに4番目の方法をお勧めします。これには、合計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)
);
custom_typesのtype_id列は、共有主キーです。主キーと外部キーの両方として宣言されており、自動番号を使用していないことに注意してください。これは、対応するエントリのタイプの主キーのコピーです。カスタムタイプテーブルには、カスタムタイプには存在するが、プリセットタイプには存在しないすべてのデータが含まれています。
プリセットタイプの場合、タイプでエントリが作成されますが、custom_typesではエントリが作成されません。 custom_typesの場合、最初にtypesでエントリが作成され、次にtype_idの結果の値がaccount_idとともにcustom_typesにコピーされます。
INNER JOINタイプとcustom_typesを使用すると、プリセットタイプは結合から外れます。 1つの結合でカスタムタイプとプリセットタイプの両方が必要な場合は、LEFTJOINまたはRIGHTJOINを使用してその効果を得る必要があります。 LEFTまたはRIGHTJOINの結果には、それらのNULLがデータベースに保管されていなくても、いくつかのNULLが含まれることに注意してください。
この