多くの人は、これらすべてのルールをアプリケーション コードで強制しています。つまり、「単純に」間違ったデータを挿入しません。もちろん、これは非常に脆弱であり、常に完璧なアプリケーション コードを作成する必要があります。そのため、間違ったデータが挿入されないように、代わりにデータベースに制約を適用する必要があります。
CREATE TABLE A (
id INT PRIMARY KEY,
type CHAR(1) NOT NULL,
unique key (id, type)
);
CREATE TABLE B (
id INT PRIMARY KEY,
type CHAR(1) NOT NULL DEFAULT 'B',
FOREIGN KEY (id, type) REFERENCES A(id, type)
);
B.type を常に 'B' にする (CHECK 制約、トリガー、または 1 行のルックアップ テーブルを参照する) ことができる場合は、もちろん type='B' である A の親行を参照できます。そして、テーブル C と D で同様のことを行うと、A の各行は、1 つのサブタイプ テーブルからの行だけで参照できるようになります。
つまり、特定の行で A.type が 'B' であり、C.type が 'C' のみである場合、C の行は A.type が 'B' である行を参照できません。
テーブル Z が B または C を参照し、D を参照しないようにする場合は、IDとタイプで参照できるため、Z にも独自のタイプ列があります。ルックアップ テーブルを使用して Z.type を制限できます。
CREATE TABLE Ztypes (
type CHAR(1) PRIMARY KEY
);
INSERT INTO Ztypes VALUES ('B'), ('C');
CREATE TABLE Z (
id INT PRIMARY KEY,
Aid INT NOT NULL,
type CHAR(1) NOT NULL,
FOREIGN KEY (Aid, type) REFERENCES A(id, type),
FOREIGN KEY (type) REFERENCES Ztypes(type)
);