【问题标题】:In MySQL, why do I have to define ForeignKey relationships?在 MySQL 中,为什么我必须定义 ForeignKey 关系?
【发布时间】:2011-11-22 19:11:21
【问题描述】:

为什么我不能把这些关系排除在外?

它们有什么意义?

我自己仍然可以运行查询并将它们视为一种关系...

【问题讨论】:

  • 比你想象的还要糟糕:外键会减慢更新速度!但正如其他人所敦促的那样,在你解雇 FK 之前,请阅读 data integrity constraints

标签: mysql sql database relational-database


【解决方案1】:

是的,您始终可以忽略外键约束,但您将对数据的完整性负责。如果您使用外键约束,那么您将不必担心表之间的引用完整性。您可以从Wikipedia 阅读有关参照完整性的更多信息。下面我也会试着用一个例子来解释一下。

想象一个购物车场景。您有三个表:itemshopping_cartshopping_cart_item。您可以选择不定义这些表之间的任何关系,这对于任何 SQL 解决方案都很好。当用户开始购物时,您可以通过添加 shopping_cart 条目来创建购物车。当用户将商品添加到他的购物车时,您可以通过将行添加到 shopping_cart_item 表来保存此信息。

在这一步可能会出现一个问题:如果你有一个错误的代码将不正确的shopping_cart_id's 分配给shopping_cart_items,那么你肯定会得到不正确的数据!是的,如果分配的 id 确实存在于 shopping_cart 表中,即使有外键约束,您也可以遇到这种情况。但是当存在外键时,这个错误会更容易被检测到,因为当外键约束失败时它不会插入shopping_cart_item 记录。

让我们继续假设您的代码没有错误并且您不会拥有第一类引用完整性。然后突然一个用户想要停止购物并删除购物车,而您选择通过删除shopping_cartshopping_cart_item 条目来实现这种情况。然后,您必须使用两个单独的查询删除两个表中的条目。如果删除shopping_cart 条目后出现问题,那么您将再次遇到参照完整性问题:您将拥有与任何shopping_cart 无关的shopping_cart_items。然后,您将不得不引入事务管理,尝试为您的业务逻辑提供有关数据访问层中发生的错误等有意义的数据。

在这种情况下,外键可以挽救生命。您可以定义一个外键约束来防止插入任何不正确的数据,并且您可以定义将自动执行相关数据删除的级联操作。

如果有什么不清楚的地方,请发表评论,我可以改进答案。

【讨论】:

  • 数据完整性是什么意思?
【解决方案2】:

除了其他人所说的您在技术上想要(实际上:需要)它们的原因:
外键约束也记录您的模型。

查看没有 FK 约束的模型时,您不知道哪个表与哪个表相关。但是有了 FK 约束,您会立即看到事物是如何相互关联的。

【讨论】:

    【解决方案3】:

    您创建 FOREIGN KEY 以指示数据库引擎确保您永远不会对创建无效记录的数据库执行操作。

    因此,如果您在users.idvisits.userid 之间创建外键关系,引擎将拒绝执行任何导致visits 中的userid 值在users 中不存在的操作。这可能是将未知的userid 添加到visits,从users 中删除已存在于visits 中的id,或者更新任一字段以“破坏”关系。

    这就是为什么主键和外键被称为参照完整性约束。告诉您的数据库引擎如何保持您的数据正确。

    【讨论】:

    • “主键和外键被称为关系完整性约束”——它们是?! SQL 标准规范故意避免使用术语“关系”及其派生词。我认为您的意思是,“FOREIGN KEYs 被称为参照完整性约束。”注意 FK 可以引用 UNIQUE 约束,我不认为 PK 是参照完整性约束。
    • 没错。对于“关系”,我的意思是写“参考”。但主键和唯一键肯定是参照完整性系统的一部分。
    【解决方案4】:

    它不允许您输入另一个表中不存在的 id,例如,如果您有产品并保留所有者 ID,则通过在所有者表的所有者 id 到 id 字段中创建外键,您不允许用户创建具有所有者表中不存在的所有者 ID 的对象记录。这样的东西叫referential intergrity.

    【讨论】:

      【解决方案5】:

      外键约束帮助您确保参照完整性。

      如果删除一个表中的一行,mysql可以自动删除被删除行通过外键引用的其他表中的所有行。你也可以让它拒绝删除命令。

      另外当你尝试插入一行时,mysql可以自动在其他表中创建新行,所以外键不引用任何东西。

      这就是参照完整性的意义所在。

      【讨论】:

        【解决方案6】:

        数据库不仅会受到应用程序的影响。并非所有数据更改都会通过应用程序,即使它们应该如此。人们总是直接在数据库上更改内容。需要始终适用于所有数据的规则属于数据库。假设您可以更新股票价格。这对于更新单个价格非常有用。但是当老板决定将所有价格提高 15% 时会发生什么。没有人会通过 GUI 一次更改 10,000 个价格,他们将编写一个快速 SQL 脚本来进行更新。或者假设两个供应商联合成立一家公司,您想将所有项目更改为新公司。数据库每天都会发生这些变化,它们也需要遵循数据完整性规则。

        新开发人员可能不知道应该存在外键关系的所有位置,因此会犯错误,导致数据不再有用。

        没有外键约束的数据库几乎有 100% 的机会在其中包含错误数据。您是否真的希望获得无法识别客户是谁的订单?

        FKS 将阻止您删除有订单的客户,或者如果您使用 company_name 的自然键并且名称更改,则所有相关记录都必须随键更改而更改。

        或者假设您决定将新的 GUI 放在一起并转储旧的 GUI,那么您可能必须再次找出所有 FK 关系(因为您使用的是不同的数据层或 ORM)并且您可能会错过一些.

        不建立FK关系是极端不负责任的。您正在冒着公司业务命脉的风险,因为您认为这样做很痛苦。如果你建议不使用 FK,我会解雇你,因为我知道我无法将我公司的数据信任给你。

        【讨论】:

        • “没有外键约束的数据库几乎有 100% 的机会在其中包含错误数据”——我完全同意。再说一次,没有CHECK 约束的数据库几乎有 100% 的机会在其中包含错误数据,因此这将适用于 mySQL 上 100% 的数据库;)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-07
        • 1970-01-01
        • 2016-07-24
        • 2021-12-25
        • 1970-01-01
        • 2010-12-30
        相关资源
        最近更新 更多