对同一个表使用多个 FK(外键)没有任何问题。只要某些列的子行应始终显示为其他某些列的子行(如果这还不是其他已声明的 FK 的结果),只需声明一个 FK。
所以直截了当的设计更好:
person1(id,name, birthCity, workCity, homeCity)
city(id, latCoord, longCoord, name)
另一个简单的设计是:
person(id, name)
city(id, latCoord, longCoord, name)
birth_city(id, cityId)
work_city(id, cityId)
home_city(id, cityId)
这里有一个约束,您需要为每个 X select id fromX_city = select id from person 添加一个约束,即两者都有 FK与人的方式。但是,如果每个城市的人员信息是可选的,那么这些仅引用人员的 FK 约束的表将是自然的。
而在您的替代设计中,数据库状态仅在 person、person_city 甚至 person_city_rel_type 具有满足某个复杂约束的值时才有效。即每个人的 id,并且只有人的 id,出现在 person_city 中,恰好具有三个类型值 id,而 person_city_rel_type 恰好具有该值。即满足某个复杂的约束条件,包括某些选择from person_city_rel_type join person_city 等于X_citys 并且如上所述它们是person1 的投影。
当您开始看到需要保持可以用更简单的表表达的约束时,是时候考虑使用更简单的表了。
PS 你的第二个提案也可以是person_city1(person_id, city_id, type)。确实,这允许无效的类型值,而要在您的设计中获得无效的 person_city(假设 person_city_rel_type_id FK),您必须搞砸 person_city_rel_type。但是模式实际上并没有阻止你这样做。任何一种设计都需要将类型列限制为三个值。所以使用 ids 代替字符串并不能解决这个问题。