我有一个带有以下字段的表my_table:id_a,id_b。 所以这个表基本上可以引用table_a中带有id_a的行,或者带有id_b的table_b中的行。如果我从table_a引用一行,则id_b为NULL。如果我从table_b引用一行,则id_a为NULL。
目前我觉得这是我唯一/最好的选择,所以在我的表格中(还有更多其他字段,顺便说一下)我会认为总是有一个字段是NULL。
如果您关心这是为了什么:如果指定了id_a,我将链接到我的元数据库中的“数据类型”记录集,该记录指定特定的数据类型。比如varchar(40)。但是如果指定了id_b,我将链接到关系定义记录集,该记录集指定关系的详细信息(通过它是1:1,1:n,链接什么,使用哪些约束等)。当然,字段被称为更好一点;)...只是尝试将其简化为问题。
编辑:如果重要:MySQL,最新版本。但是不要想尽可能地将我的设计限制在MySQL特定代码中。
有更好的解决方案吗?
答案 0 :(得分:4)
A
和B
是模型中不相交的子类型。
这可以这样实现:
refs (
type CHAR(1) NOT NULL, ref INT NOT NULL,
PRIMARY KEY (type, ref),
CHECK (type IN ('A', 'B'))
)
table_a (
type CHAR(1) NOT NULL, id INT NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (type, id) REFERENCES refs (type, id),
CHECK (type = 'A'),
…)
table_b (
type CHAR(1) NOT NULL, id INT NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (type, id) REFERENCES refs (type, id) ON DELETE CASCADE,
CHECK (type = 'B'),
…)
mytable (
type CHAR(1) NOT NULL, ref INT NOT NULL,
FOREIGN KEY (type, ref) REFERENCES refs (type, id) ON DELETE CASCADE,
CHECK (type IN ('A', 'B')),
…)
表refs
会保留A
和B
的所有实例。除了监管参照完整性之外,它没有任何其他用途,它甚至不会参与连接。
请注意,MySQL
接受CHECK
个约束但不强制执行。你需要注意你的类型。
您也不应直接从table_a
和table_b
删除记录:而是删除refs
中将触发ON DELETE CASCADE
的记录。
答案 1 :(得分:3)
为A和B创建父“超类型”表。在my_table中引用该表。
答案 2 :(得分:1)
是的,有更好的解决方案。
但是,由于您没有描述允许更改的内容,因此很难知道可以使用哪些替代方案。
主要地,这种“异或”类的关键引用意味着A和B实际上是公共超类的两个子类。您可以通过多种方式更改A和B表,以将它们统一到一个表中。
其中一个就是简单地将A和B表合并为一个大表。
另一个是拥有一个具有A和B共同特征的超类表,以及一个描述它是哪个子类型的子类型标志。这仍然涉及与子类表的连接,但是连接具有显式鉴别器,并且可以由应用程序“懒惰地”而不是在SQL中完成。
答案 3 :(得分:0)
我认为您的解决方案没有问题。但是,我认为你应该添加CHECK约束以确保其中一个字段为空。
答案 4 :(得分:0)
你知道,因为你已经剥夺了所有重要信息的问题,所以很难说是否有更好的解决方案。只有少量仍然在那里,我会说最好的解决方案涉及摆脱my_table
。