私は "is a"関係(別名継承)を使用していくつかのモデルを作成していますが、継承されたテーブルの主キーと親テーブルを指す外部キーに関して、2つの方法があります。
戦略#1は、継承された各テーブルに常に新しいサロゲートキーを作成し、親テーブルの主キーへの参照を別の列に格納することです(1対1のマッピングを確実にするために、その列に一意の制約を設定します)。
戦略#2は、継承されたテーブルの主キー値を親テーブルの主キーと同じ値にすることでした。
ここには明確な勝者がいると思います(戦略#2)が、見逃していない潜在的な問題がないことを確認したいと思います。
以下は、各戦略を詳細に記述したコード(SQL Serverを対象としていますが、汎用的なもの)です。
------Strategy #1: always create a surrogate key for a child table (separate column holds parent table's primary key)----------
drop table if exists TruckAsset
drop table if exists VehicleAsset
drop table if exists Asset
create table Asset
(
AssetId int not null,
primary key (AssetId)
)
create table VehicleAsset
(
VehicleAssetId int not null, /*surrogate key*/
AssetId int not null,
VehicleRegistrationExpirationDate date not null, /*specialization of Asset*/
primary key (VehicleAssetId),
constraint UQ_AssetId unique (AssetId),
foreign key (AssetId) references Asset(AssetId)
)
create table TruckAsset
(
TruckAssetId int not null, /*surrogate key*/
VehicleAssetId int not null,
CargoCapacityCubicMeters float not null, /*specialization of VehicleAsset*/
primary key (TruckAssetId),
constraint UQ_VehicleAssetId unique (VehicleAssetId),
foreign key (VehicleAssetId) references VehicleAsset(VehicleAssetId)
)
INSERT INTO Asset(AssetId)VALUES(1234)
INSERT INTO VehicleAsset(VehicleAssetId, AssetId, VehicleRegistrationExpirationDate) VALUES (5678, 1234, '2020-01-01')
INSERT INTO TruckAsset(TruckAssetId, VehicleAssetId, CargoCapacityCubicMeters) VALUES (9999, 5678, 8.80977)
GO
これに対して
------Strategy #2: primary key references parent table's primary key directly----------
drop table if exists TruckAsset
drop table if exists VehicleAsset
drop table if exists Asset
create table Asset
(
AssetId int not null,
primary key (AssetId)
)
create table VehicleAsset
(
VehicleAssetId int not null,
VehicleRegistrationExpirationDate date not null, /*specialization of Asset*/
primary key (VehicleAssetId),
foreign key (VehicleAssetId) references Asset(AssetId)
)
create table TruckAsset
(
TruckAssetId int not null,
CargoCapacityCubicMeters float not null, /*specialization of VehicleAsset*/
primary key (TruckAssetId),
foreign key (TruckAssetId) references VehicleAsset(VehicleAssetId)
)
INSERT INTO Asset(AssetId)VALUES(1234)
INSERT INTO VehicleAsset(VehicleAssetId, VehicleRegistrationExpirationDate) VALUES (1234, '2020-01-01')
INSERT INTO TruckAsset(TruckAssetId, CargoCapacityCubicMeters) VALUES (1234, 8.80977)
----------------------------------------
戦略#2には名前があります。これは共有主キーと呼ばれます。広く使用されているのは型の関係です。 Stackoverflowには、この概念に関連する質問をグループ化するタグオーバーがあります。