継承を使用しています(エンティティ関係モデリングでは「サブクラス」または「カテゴリ」とも呼ばれます)。一般に、データベースでそれを表すには3つの方法があります。
- 「1つのテーブル内のすべてのクラス」: 親クラスとすべての子クラスを「カバー」するテーブルを1つだけ(つまり、すべての親列と子列を含む)、フィールドの正しいサブセットがNULLでないことを確認するためのCHECK制約を設定します(つまり、2つの異なる子が「混合」しない)。
- 「テーブルごとの具象クラス」: 子ごとに異なるテーブルを用意しますが、親テーブルはありません。これには、すべての子で親の関係(この場合は在庫<-ストレージ)を繰り返す必要があります。
- 「テーブルごとのクラス」: 親テーブルと子ごとに個別のテーブルを用意します。これが、あなたがやろうとしていることです。これは最もクリーンですが、パフォーマンスがいくらか犠牲になる可能性があります(主にデータを変更する場合、子から直接参加して親をスキップできるため、クエリの場合はそれほど多くありません)。
私は通常3番目のアプローチを好みますが、両方のプレゼンスを強制します および独占性 アプリケーションレベルでの子供のデータベースレベルで両方を適用するのは少し面倒ですが、DBMSが遅延制約をサポートしている場合は実行できます。例:
CHECK (
(
(VAN_ID IS NOT NULL AND VAN_ID = STORAGE_ID)
AND WAREHOUSE_ID IS NULL
)
OR (
VAN_ID IS NULL
AND (WAREHOUSE_ID IS NOT NULL AND WAREHOUSE_ID = STORAGE_ID)
)
)
これにより、両方の排他性が適用されます(CHECK
による) )とプレゼンス(CHECK
の組み合わせによる) およびFK1
/ FK2
)子供の。
残念ながら、MS SQL Serverは遅延制約をサポートしていませんが、ストアドプロシージャの背後で操作全体を「非表示」にし、クライアントがテーブルを直接変更することを禁止できる場合があります。
延期された制約なしに、排他性のみを適用できます:
STORAGE_TYPE
は型識別子であり、通常はスペースを節約するための整数です(上記の例では、0と1はアプリケーションに「認識」されており、それに応じて解釈されます)。
VAN.STORAGE_TYPE
およびWAREHOUSE.STORAGE_TYPE
ストレージを節約し、CHECK
の必要性を回避するために、計算(別名「計算済み」)列を使用できます。 s。
---編集---
計算列は、SQLServerでは次のように機能します。
CREATE TABLE STORAGE (
STORAGE_ID int PRIMARY KEY,
STORAGE_TYPE tinyint NOT NULL,
UNIQUE (STORAGE_ID, STORAGE_TYPE)
);
CREATE TABLE VAN (
STORAGE_ID int PRIMARY KEY,
STORAGE_TYPE AS CAST(0 as tinyint) PERSISTED,
FOREIGN KEY (STORAGE_ID, STORAGE_TYPE) REFERENCES STORAGE(STORAGE_ID, STORAGE_TYPE)
);
CREATE TABLE WAREHOUSE (
STORAGE_ID int PRIMARY KEY,
STORAGE_TYPE AS CAST(1 as tinyint) PERSISTED,
FOREIGN KEY (STORAGE_ID, STORAGE_TYPE) REFERENCES STORAGE(STORAGE_ID, STORAGE_TYPE)
);
-- We can make a new van.
INSERT INTO STORAGE VALUES (100, 0);
INSERT INTO VAN VALUES (100);
-- But we cannot make it a warehouse too.
INSERT INTO WAREHOUSE VALUES (100);
-- Msg 547, Level 16, State 0, Line 24
-- The INSERT statement conflicted with the FOREIGN KEY constraint "FK__WAREHOUSE__695C9DA1". The conflict occurred in database "master", table "dbo.STORAGE".
残念ながら、SQLServerでは外部で使用される計算列が必要です。 永続化するためのキー。他のデータベース(Oracleの仮想列など)にはこの制限がない場合があり、ストレージスペースを節約できます。