我有表A,表B和表C.表C有一列,它应该是PK的FK。 PK可以是表A的id或表B的id。设计此类表格的最佳做法是什么?
我正在考虑在表C中创建2列,其中第一列将确定表A或表B,第二列表示表A或表B的ID(取决于第一列)。这是正确的方法吗?
答案 0 :(得分:1)
请参阅:http://www.sqlfiddle.com/#!8/3519e/4
我用3个表做了一个例子:
您可以创建一个查询以使用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中不存在此限制。