当前位置:  开发笔记 > 编程语言 > 正文

像数据库设计中的继承之类的东西

如何解决《像数据库设计中的继承之类的东西》经验,为你挑选了2个好方法。

假设您正在设置数据库来存储各种车辆的碰撞测试数据.您想存储快艇,汽车和卡丁车的碰撞测试数据.

您可以创建三个单独的表:SpeedboatTests,CarTests和GokartTests.但是每个表中的很多列都是相同的(例如,执行测试的人员的员工ID,碰撞的方向(正面,侧面,后面)等).但是,很多列都会有所不同,因此您不希望将所有测试数据放在一个表中,因为您将拥有相当多的列,对于快艇来说总是为空,相当多的列始终是对于汽车来说是零,而对于卡丁车来说,相当多的都是空的.

假设您还想存储一些与测试没有直接关系的信息(例如正在测试的东西的设计者的员工ID).这些列根本不适合放入"测试"表,特别是因为它们将在同一车辆上的所有测试中重复使用.

让我说明一种可能的表格排列,以便您可以看到所涉及的问题.

Speedboats
id | col_about_speedboats_but_not_tests1 | col_about_speedboats_but_not_tests2

Cars
id | col_about_cars_but_not_tests1 | col_about_cars_but_not_tests2

Gokarts
id | col_about_gokarts_but_not_tests1 | col_about_gokarts_but_not_tests2

Tests
id | type | id_in_type | col_about_all_tests1 | col_about_all_tests2
(id_in_type will refer to the id column of one of the next three tables,
depending on the value of type)

SpeedboatTests
id | speedboat_id | col_about_speedboat_tests1 | col_about_speedboat_tests2

CarTests
id | car_id | col_about_car_tests1 | col_about_car_tests2

GokartTests
id | gokart_id | col_about_gokart_tests1 | col_about_gokart_tests2

这个结构的优点/缺点是什么,实现这样的优先方式是什么?

如果还有一些信息适用于您希望在车辆表中使用的所有车辆,该怎么办?那么CarTests表看起来像......

id | vehicle_id | ...

With a Vehicles table like this:
id | type | id_in_type
(with id_in_type pointing to the id of either a speedboat, car, or go-kart)

这似乎是一场皇家般的混乱.应该如何设置这样的东西?



1> Bill Karwin..:

typeid_in_type设计被称为多态关联.这种设计以多种方式打破了规范化规则.如果没有别的,它应该是一个红旗,你不能声明一个真正的外键约束,因为它id_in_type可以引用几个表中的任何一个.

这是定义表的更好方法:

制作一个抽象表Vehicles,为所有车辆子类型和车辆测试提供抽象参考点.

每个车辆子类型都有一个不会自动递增的主键,而是引用Vehicles.

每个测试子类型都有一个不会自动递增的主键,而是引用Tests.

每个测试子类型还具有对应的车辆子类型的外键.

这是DDL的示例:

CREATE TABLE Vehicles (
 vehicle_id INT AUTO_INCREMENT PRIMARY KEY
);

CREATE TABLE Speedboats (
 vehicle_id INT PRIMARY KEY,
 col_about_speedboats_but_not_tests1 INT,
 col_about_speedboats_but_not_tests2 INT,
 FOREIGN KEY(vehicle_id) REFERENCES Vehicles(vehicle_id)
);

CREATE TABLE Cars (
 vehicle_id INT PRIMARY KEY,
 col_about_cars_but_not_tests1 INT,
 col_about_cars_but_not_tests2 INT,
 FOREIGN KEY(vehicle_id) REFERENCES Vehicles(vehicle_id)
);

CREATE TABLE Gokarts (
 vehicle_id INT PRIMARY KEY,
 col_about_gokarts_but_not_tests1 INT,
 col_about_gokarts_but_not_tests2 INT,
 FOREIGN KEY(vehicle_id) REFERENCES Vehicles(vehicle_id)
);

CREATE TABLE Tests (
 test_id INT AUTO_INCREMENT PRIMARY KEY,
 col_about_all_tests1 INT,
 col_about_all_tests2 INT
);

CREATE TABLE SpeedboatTests (
 test_id INT PRIMARY KEY,
 vehicle_id INT NOT NULL,
 col_about_speedboat_tests1 INT,
 col_about_speedboat_tests2 INT,
 FOREIGN KEY(test_id) REFERENCES Tests(test_id),
 FOREIGN KEY(vehicle_id) REFERENCES Speedboats(vehicle_id)
);

CREATE TABLE CarTests (
 test_id INT PRIMARY KEY,
 vehicle_id INT NOT NULL,
 col_about_car_tests1 INT,
 col_about_car_tests2 INT,
 FOREIGN KEY(test_id) REFERENCES Tests(test_id),
 FOREIGN KEY(vehicle_id) REFERENCES Cars(vehicle_id)
);

CREATE TABLE GokartTests (
 test_id INT PRIMARY KEY,
 vehicle_id INT NOT NULL,
 col_about_gokart_tests1 INT,
 col_about_gokart_tests2 INT,
 FOREIGN KEY(test_id) REFERENCES Tests(test_id),
 FOREIGN KEY(vehicle_id) REFERENCES Gokarts(vehicle_id)
);

您也可以在每个测试子类型表中声明Tests.vehicle_id哪些引用Vehicles.vehicle_id并删除vehicle_id外键,但这将允许异常,例如引用gokart id的快艇测试.


所有其他答案除了这一个,也许,[提到马丁福勒的那个](http://stackoverflow.com/a/554552/279564),应该被删除或埋没到遗忘... OMG ..

2> hallidave..:

为了将继承层次结构映射到数据库表,我认为Martin Fowler在他的"企业应用程序架构模式"一书中详细阐述了替代方案.

http://martinfowler.com/eaaCatalog/singleTableInheritance.html

http://martinfowler.com/eaaCatalog/classTableInheritance.html

http://martinfowler.com/eaaCatalog/concreteTableInheritance.html

如果子类的附加字段/列数很少,那么单表继承通常最容易处理.

如果您正在为数据库使用PostgreSQL,并且您愿意将自己绑定到特定于数据库的功能,则它直接支持表继承:

http://www.postgresql.org/docs/8.3/static/ddl-inherit.html

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