如何解决A / B键问题?

时间:2009-12-30 11:31:24

标签: database database-design

我有一个带有以下字段的表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特定代码中。

有更好的解决方案吗?

5 个答案:

答案 0 :(得分:4)

AB是模型中不相交的子类型。

这可以这样实现:

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会保留AB的所有实例。除了监管参照完整性之外,它没有任何其他用途,它甚至不会参与连接。

请注意,MySQL接受CHECK个约束但不强制执行。你需要注意你的类型。

您也不应直接从table_atable_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