单个FK是指来自多个表的PK

时间:2013-04-30 19:47:46

标签: mysql sql database database-design

我有表A,表B和表C.表C有一列,它应该是PK的FK。 PK可以是表A的id或表B的id。设计此类表格的最佳做法是什么?

我正在考虑在表C中创建2列,其中第一列将确定表A或表B,第二列表示表A或表B的ID(取决于第一列)。这是正确的方法吗?

2 个答案:

答案 0 :(得分:1)

使用SQL UNION将两个ResultSet与不同的连接组合

请参阅:http://www.sqlfiddle.com/#!8/3519e/4

我用3个表做了一个例子:

  • CAR
  • 卡车
  • DRIVER_ASSIGNED

您可以创建一个查询以使用C连接A,使用C连接另一个查询,并使用UNION连接两个结果集。例如:

(select * from `A`, 
`C`
where `A`.ID = `C`.`ID` and
`C`.`Type` like 'A')
UNION
(select * from `B`, 
`C`
where `B`.ID = `C`.`ID` and
`C`.`Type` like 'B')

与类和子类相关

似乎表A和表B是另一种类型/类的子类型。所以,例如表A可以是汽车,而表B可以是卡车,但它们可以延伸车辆。

在这种情况下,我认为你需要第四个表TABLE PARENT,它将结合A和B的公共字段.C将使用TABLE PARENT的主键作为外来K.

表A和B将包含两个外键,但也可能作为表PARENT主键的主键。

因此,使用我对车辆的比喻让我们假设:

    TABLE A = CARS
    TABLE B = TRUCKS
    TABLE C = ASSIGNED_DRIVERS
    TABLE PARENT = VEHICLES

    TABLE VEHICLES - PARENT of A and B
    -------------
    ID (PK)
    HORSE POWER
    LICENSE PLATE
    etc...

    TABLE CARS - 
    -------------
    ID (PK)
    VEHICLE_ID (FK linking to VEHICLES.ID)
    NUMBER_SEATS
etc...

    TABLE TRUCKS - 
    -------------
    ID (PK)
    VEHICLE_ID (FK linking to VEHICLES.ID)
    HIGHT (meters)
    MAXIMUM_STORAGE_WEIGHT
etc...


    TABLE DRIVERS_ID - 
    -------------
    VEHICLE_ID (FK linking to VEHICLES.ID)
    DRIVER_OD
  START_DATE
END_DATE
etc...

因此,以下方法可以帮助您避免此问题,并且在语义上更正确。

您还可以查看在线文档,例如:

http://www.dssbooks.com/web/Files/LookInside/Web-DSS-Chapter-03.pdf(第55页),了解类和子类之间的理论。

答案 1 :(得分:1)

  

我正在考虑在表C中创建2列,其中第一列将确定表A或表B,第二列表示表A或表B的ID(取决于第一列)。这是正确的方法吗?

没有。您将阻止DBMS强制执行外键。您必须通过触发器或应用程序代码强制执行FK,这更容易出错并且可能性能较差。

创建两个FK字段(一个用于表A,另一个用于表B)并使用CHECK 1 来确保其中只有一个不为NULL,或者使用继承。

this post中的更多信息。


1 不幸的是,MySQL解析了doesn't enforce CHECK约束,所以你需要使用触发器。其他DBMS中不存在此限制。