当前位置:  开发笔记 > 后端 > 正文

如何模拟数据库中的标记联合?

如何解决《如何模拟数据库中的标记联合?》经验,为你挑选了2个好方法。

在数据库中模拟Tagged union的最佳方法是什么?我在谈论这样的事情:

create table t1 {
  vehicle_id INTEGER NOT NULL REFERENCES car(id) OR motor(id) -- not valid
  ...
}

其中vehicle_id将在汽车表或电机表中为id,并且它将知道哪个.

(假设电动机和汽车桌没有任何共同点



1> Bill Karwin..:

有些人使用一种名为Polymorphic Associations的设计来执行此操作,允许vehicle_id包含存在于carmotor表中的值.然后添加一个vehicle_type命名t1引用中给定行的表的名称.

问题是,如果执行此操作,则无法声明真正的SQL外键约束.SQL中不支持具有多个引用目标的外键.还有其他问题,但缺乏参照完整性已经成为一种交易破坏者.

更好的设计是从OO设计中借用两种常见超类型的概念,car并且motor:

CREATE TABLE Identifiable (
 id SERIAL PRIMARY KEY
);

然后t1引用这个超类型表:

CREATE TABLE t1 (
  vehicle_id INTEGER NOT NULL,
  FOREIGN KEY (vehicle_id) REFERENCES identifiable(id)
  ...
);

并且还使子类型引用其父类型.请注意,子类型的主键不是自动递增.父超类型负责分配新的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)
  ...
);

现在,您可以拥有真正的参照完整性,但也支持具有各自属性的多个子类型表.


@Quassnoi的答案还显示了一种强制不相交的子类型的方法.也就是说,你想阻止都carmotor在它们的父父表引用同一行.当我这样做时,我使用单列主键,Identifiable.id但也声明了一个UNIQUEIdentifiable.(id, type).外键中的carmotor可以引用两列唯一键而不是主键.



2> Quassnoi..:
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
  ...
)

推荐阅读
k78283381
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有