【发布时间】:2022-11-24 05:10:22
【问题描述】:
我有一个多态结构的数据库:一个“基本”类型表和两个“派生”类型:
CREATE TABLE ContactMethod(
id integer PRIMARY KEY
person_id integer
priority integer
allow_solicitation boolean
FOREIGN KEY(person_id) REFERENCES People(id)
)
CREATE TABLE PhoneNumbers(
contact_method_id integer PRIMARY KEY
phone_number varchar
FOREIGN KEY(contact_method_id) REFERENCES ContactMethod(id)
)
CREATE TABLE EmailAddresses(
contact_method_id integer PRIMARY KEY
email_address varchar
FOREIGN KEY(contact_method_id) REFERENCES ContactMethod(id)
)
我想防止孤立的 ContactMethod 记录存在,即 ContactMethod 记录既没有相应的 PhoneNumber 记录也没有 EmailAddress 记录。我见过确保排他性的技术(防止 ContactMethod 记录同时具有相关的 PhoneNumber 和 EmailAddress),但不是为了防止孤儿。
一个想法是 CHECK 约束,它执行执行查询的自定义函数。但是,通过 CHECK 约束中的函数执行查询不是一个好主意。
另一个想法是如果添加孤立的 ContactMethod 记录,将触发违规的视图。做到这一点的“明显”方法是对视图施加约束,但这是不允许的。所以它必须是某种技巧,可能涉及视图上的索引。这真的是最好的(唯一的?)强制没有孤儿的方法吗?如果是这样,什么是工作示例?
还有其他方法吗?我可以摆脱 ContactMethod 表和其他两个表上的重复共享列,但我不想那样做。我主要对 MySQL 和 SQLite 中可用的功能感到好奇,但是任何 SQL 引擎中的解决方案都会有所帮助。
【问题讨论】:
-
1) 从数据库设计的角度来看,没有电话号码和电子邮件地址行的 ContactMethod 行不是孤立的。如果人员 ID 字段为空或指向无效的父值,则 ContactMethod 行将是孤立的。正确的术语是没有孩子,而不是孤儿。 2)外键只能以相反的方式工作。 sql 中没有标准解决方案来处理此类情况。因此,您依赖于通过触发器和存储过程实现自定义代码。这些解决方案特定于您使用的数据库产品,您需要将问题缩小到一种数据库产品。
标签: mysql sql sqlite database-design class-table-inheritance