设置
我有两个 Postgres 10 表,它们有些相似但远非相同:
MotorVehicles
Id (auto-incrementing int)
PaintColor (varchar; not null)
EngineSize (int; not null)
Capacity (int)
和
Trailers
Id (auto-incrementing int)
PaintColor (varchar; not null)
AttachedVehicle (int; not null; foreign key referring to MotorVehicles Id)
Capacity (int)
两者都是在路上行驶的东西,并且有一些共同的属性,尽管一个明显地依附于另一个(一辆卡车可以有多个拖车,而且——至少就我的目的而言——一个拖车不应该单独存在)。
我正在尝试设计一个可应用于 MotorVehicle
或 Trailer
的事物表:LicensePlates
。
LicensePlates
PlateNumber (varchar; not null)
Issuer (varchar)
ExpirationDate (timestamp)
... some kind of reference to the above tables ...
我不确定如何完成 LicensePlates
表,因为 MotorVehicles
和 Trailers
之间没有唯一标识符(例如,它们可以每个都有 ID 号为 1 的行,这些东西不会相同,所以我不能在 LicensePlates
中只有一个 ParentId
属性。
约束
任何给定的 LicensePlate 类型行必须引用恰好一个机动车或拖车,但不能同时引用两者,也不能两者都引用。但是,给定的机动车或拖车可能有多个牌照(例如,一个来自加拿大省,一个来自欧洲国家);甚至根本没有印版(如果它是刚从工厂出来但尚未注册或存储的)。
选项
我实际上应该如何设计 LicensePlates
?我想出了几个选项:
- 将
MotorVehicles
和Trailers
合并到一个ThingsOnTheRoad
表中,这样 ID 就不会冲突- 我反对这样做,因为每个现有表都有一些对另一个表没有语义意义的属性,而且这会干扰约束
- 在
LicensePlates
中,将相关表中的 ID 保存在一列中,将其引用的表保存在另一列中- 这似乎是最直接的,但也很不优雅。
- 创建一个跨越两个表的自动递增列,因此永远不会有 ID 号冲突
- 来自 what I've read ,这实际上是不可能的,而且即使它是唯一的,也可能会让人头疼地弄清楚该 ID 属于哪个表
- 用 GUID 替换现有的自动递增 ID
- 可以工作,但会影响人类的可读性
- 以某种方式合并
MotorVehicles
和Trailers
以获得第二个选项的所有好处,但没有缺点- 这看起来很吸引人,但我对如何实际设置它一无所知
那我到底在做什么呢?还有其他我没有列出的选项吗?特别是,是否可以设置我最后提到的 View ,如果可以,如何设置?
(您可能已经猜到了,这些不是我的真实表格,但它们确实模拟了关系的要点。)
最佳答案
第二种选择是完美的,它被称为多态关系。我在我的几个 Rails 应用程序中广泛使用的概念来满足此类需求。
简而言之,LicencePlates
表应该有两列,VehicleID
和 VehicleType
。 VehicleID
存储 MotorVehicles
或 Trailers
的 id,VehicleType
可以引用从中引用 id 的表.
这种方法有很多优点。
- 明确性 - 您知道所引用的表和 ID。
- 简单 - 它非常简单,您不必管理 ID、GUID、它们的序列等。DB 擅长管理某些东西,例如 ID,使用它,不要低估它。
- 可维护性 - 不仅在代码层面,还有附加概念 - 将 LicencePlate 分离到特定资源(Trailer/MotorVehicle)很容易维护。两者都是在道路上行驶的车辆,但具有不同的用途、访问模式、信息、验证等。
关于sql - 设计可以引用多个其他表的数据库表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49479011/