【问题标题】:mysql/RoR database designmysql/RoR 数据库设计
【发布时间】:2013-06-12 22:44:49
【问题描述】:

一个表可以有两个相同的外键作为列吗?

即我有两张桌子,一张是 Country,另一张是 City。在国家表中:

国家
--------------
身份证
名称
capitalcity populouscity

城市
--------
身份证
名称
人口众多(布尔)
大写(布尔)
created_at
更新时间

请记住,首都可能是人口最多的城市,也可能不是。 我想知道我是否应该将城市的两个布尔列分开,将城市作为只有名称的城市,并有一个引用城市的人口众多的表,以及引用城市的资本。并且在这两个新表的国家表中有两个单独的外键?

【问题讨论】:

    标签: mysql database ruby-on-rails-3 database-design


    【解决方案1】:

    我会这样设计

    COUNTRY
    --------------
    id
    name    
    
    CITY
    -------
    id
    country_id   ( useful to know what country a city is in  )
    name
    created_at
    updated_at
    
    CAPITALS
    ----------
    id
    city_id         Unique
    
    POPULUS
    -------
    id
    city_id         Unique
    

    【讨论】:

    • 非常感谢您的回答。似乎我忘了换个角度思考……城市可以属于国家。哦!
    • @DeiS 此设计并未模拟您的要求(如您的问题中当前所述)。例如,没有什么可以阻止一个国家​​拥有多个首都或多个“人口最多”的城市。 country_id 可以放在大写字母和 POPULOUS 中(与编辑之前一样),但这仍然允许一个城市成为它不属于的国家的首都,除非您使用标识关系,但随后这个设计开始接近我所拥有的proposed
    • 好的,我明白你在说什么。我需要考虑清楚这一点。越来越奇怪了。这是我这部分设计的宏伟构想:国家将通过其 ISO3166-2 代码来识别,然后我将有州,可能会在国家之下分为三个级别,每个国家应该有一个首都,一个人口稠密的城市,以及那么每个州都可以有相同的。
    【解决方案2】:

    是的,没关系。人们有时会避免使用此类“明确”的 FK,因为它们不“灵活”,但如果您知道您总是需要与这两个城市完全相关,这是合适的设计。在任何情况下,您都不需要这些 FK bool 标志。

    我没有看到您如何将非首都和人口不多的城市与该国联系起来。如果您不小心设计钥匙的方式,您最终可能会遇到这样的情况:一个城市可能成为它不属于的国家的首都。

    使用识别关系可以避免这个问题:

    因此,每个城市都由其所在国家/地区的数字 (CITY_NO) 标识。当 PK 从 CITY 迁移回 COUNTRY 时,COUNTRY_ID 会“合并”回其来源,因此不会出现国家/地区不匹配(请注意 COUNTRY.COUNTRY_ID 上的 FK1 和 FK2)。

    CAPITAL_NO 和 POPULOUS_NO 可以保留为 NULL,因此它们可以暂时保持为 NULL 以解决由循环 FK 引起的先有鸡还是先有蛋的问题。这是有效的,因为 InnoDB 使用MATCH SIMPLE 方法强制执行 FK,因此只要复合 FK 的一个组件为 NULL 就足以避免 FK 违规。

    顺便说一句,考虑一下您是否真的需要 POPULOUS_ID - 如果您保留所有城市的人口,那么您只需找到 MAX 即可得出哪个城市的人口最多。

    如果您需要为子 FK 或安抚您的 ORM,您可以随时添加 CITY_ID 等代理键...

    【讨论】:

    • 我认为这是一个很好的答案,虽然我需要读几遍才能理解其中的逻辑。信不信由你,我确实在大学(10 多年前)做了 db design 到 5th nf。当实际建模特定需求时,它会变得非常混乱。谢谢
    • 我还应该指出,我正在使用 RubyOnRails 为我完成所有数据库建模关系,当我全力以赴进行设计时,我将在数据库端镜像关系并减少列。倒数第二段也是值得深思的,我的想法是在数据库中填充特定城市,即人口最多和/或首都,对于美国作为国家,这些分别是纽约和华盛顿特区,但对于英国,两者都是伦敦。谢谢
    猜你喜欢
    • 1970-01-01
    • 2018-02-06
    • 1970-01-01
    • 2014-01-12
    • 2018-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-30
    相关资源
    最近更新 更多