Łuk*_*Lew 11 mysql database sqlite postgresql
在数据库中模拟Tagged union的最佳方法是什么?我在谈论这样的事情:
create table t1 {
vehicle_id INTEGER NOT NULL REFERENCES car(id) OR motor(id) -- not valid
...
}
Run Code Online (Sandbox Code Playgroud)
其中vehicle_id将在汽车表或电机表中为id,并且它将知道哪个.
(假设电动机和汽车桌没有任何共同点
有些人使用一种名为Polymorphic Associations的设计来执行此操作,允许vehicle_id包含存在于car或motor表中的值.然后添加一个vehicle_type命名t1引用中给定行的表的名称.
问题是,如果执行此操作,则无法声明真正的SQL外键约束.SQL中不支持具有多个引用目标的外键.还有其他问题,但缺乏参照完整性已经成为一种交易破坏者.
更好的设计是从OO设计中借用两种常见超类型的概念,car并且motor:
CREATE TABLE Identifiable (
id SERIAL PRIMARY KEY
);
Run Code Online (Sandbox Code Playgroud)
然后t1引用这个超类型表:
CREATE TABLE t1 (
vehicle_id INTEGER NOT NULL,
FOREIGN KEY (vehicle_id) REFERENCES identifiable(id)
...
);
Run Code Online (Sandbox Code Playgroud)
并且还使子类型引用其父类型.请注意,子类型的主键不是自动递增.父超类型负责分配新的id值,子节点只引用该值.
CREATE TABLE car (
id INTEGER NOT NULL,
FOREIGN KEY (id) REFERENCES identifiable(id)
...
);
CREATE TABLE motor (
id INTEGER NOT NULL,
FOREIGN KEY (id) REFERENCES identifiable(id)
...
);
Run Code Online (Sandbox Code Playgroud)
现在,您可以拥有真正的参照完整性,但也支持具有各自属性的多个子类型表.
@Quassnoi的答案还显示了一种强制不相交的子类型的方法.也就是说,你想阻止都car和motor在它们的父父表引用同一行.当我这样做时,我使用单列主键,Identifiable.id但也声明了一个UNIQUE键Identifiable.(id, type).外键中的car和motor可以引用两列唯一键而不是主键.
CREATE TABLE vehicle (type INT NOT NULL, id INT NOT NULL,
PRIMARY KEY (type, id)
)
CREATE TABLE car (type INT NOT NULL DEFAULT 1, id INT NOT NULL PRIMARY KEY,
CHECK(type = 1),
FOREIGN KEY (type, id) REFERENCES vehicle
)
CREATE TABLE motorcycle (type INT NOT NULL DEFAULT 2, id INT NOT NULL PRIMARY KEY,
CHECK(type = 2),
FOREIGN KEY (type, id) REFERENCES vehicle
)
CREATE TABLE t1 (
...
vehicle_type INT NOT NULL,
vehicle_id INT NOT NULL,
FOREIGN KEY (vehicle_type, vehicle_id) REFERENCES vehicle
...
)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1930 次 |
| 最近记录: |