【问题标题】:Why do I need to use foreign key if I can use WHERE?如果可以使用 WHERE,为什么还需要使用外键?
【发布时间】:2010-12-26 19:29:25
【问题描述】:

一个关于 MySQL 中外键的初学者问题。

w3school 它说,

一个表中的 FOREIGN KEY 指向另一个表中的 PRIMARY KEY。

还有WHERE,

WHERE id = page_id

那么如果我可以使用 WHERE 来链接表,那么拥有外键的主要目的是什么?

【问题讨论】:

标签: mysql foreign-keys


【解决方案1】:

维护referential integrity 和索引。

【讨论】:

    【解决方案2】:

    【讨论】:

      【解决方案3】:

      查询并不严格需要它,这是真的。它的存在有几个原因:

      1. 作为对表的约束,以阻止您插入不指向任何内容的内容;
      2. 作为优化器的线索;和
      3. 由于历史原因,哪里更需要。

      (1) 可能是三者中最重要的一个。这称为referential integrity。这意味着如果外键中有一个值,那么在父表中就会有一条以该值作为主键的对应记录。

      话虽如此,并非所有数据库都支持参照完整性(例如 MySQL/MyISAM 表),并且那些不一定强制执行的数据库(出于性能原因)。

      【讨论】:

        【解决方案4】:

        那么如果我可以使用 WHERE 来链接表,那么拥有外键的主要目的是什么?

        因为WHERE 子句不限于外键上的等值连接。

        假设你有一个描述价格范围和折扣的表格,你可以使用这个复杂的条件来连接表格:

        SELECT  *
        FROM    Goods
        JOIN    PriceRange
        ON      PriceRange.Price =
                (
                SELECT  MAX(Price)
                FROM    PriceRange
                WHERE   PriceRange.Price <= Goods.Price
                )
        

        您不能将这些表与外键关系链接起来,但您可以轻松地加入它们。

        查看我博客中的这篇文章了解更多详情:

        不过,pk-to-pk 绑定仍然很重要。 FOREIGN KEY 可以确保您链接的实体由您的关系模型描述。

        使用支持FOREIGN KEY 的设计,您不能声明与描述该实体的表中不存在PRIMARY KEY 的实体的关系。

        SQL Server 甚至可以考虑这一事实并优化某些类型的查询。

        说,这个查询:

        SELECT  f.*
        FROM    t_foreign f
        WHERE   f.pid IN
                (
                SELECT  id
                FROM    t_primary p
                )
        

        如果在t_foreignt_primary 之间定义了FOREIGN KEY 关系,则甚至不会查看t_primary

        查看这篇文章了解更多详情:

        【讨论】:

        • 我认为 OP 是在询问如果您可以简单地编写一个可以比较任何 2 个字段的 Where 子句,外键有什么值。即使您意识到这一点,您的答案也可能需要一些简化,因为 OP 是使用 MySQL 的初学者。
        【解决方案5】:

        外键用于维护引用完整性,而 WHERE 子句用于在 SQL 操作(例如选择)中将表连接在一起。 where 子句可以跨多个表操作,但它纯粹是作为过滤器存在的。

        严格来说,您可以在没有参照完整性的情况下逃脱,但这不是一个好主意。如果没有参照完整性,您最终会依赖于您的客户端应用程序,而不会在关系链的一端错误地删除或更新某些会对数据产生连锁反应的东西,例如将键值更改为指向不存在的键值。

        参照完整性是确保相关数据以一致方式保存的好方法。

        【讨论】:

          【解决方案6】:

          WHERE 子句的主要目的是限制查询返回的行。见SELECT Syntax

          主键/外键关系保持参照完整性,并通过适当的索引提高查询性能。 (请参阅上文和 JOIN Types 的 Pete OHanlon 的解释)

          【讨论】:

            【解决方案7】:

            首先。好问题!!

            MySql 是一个 RDBMS - 关系型 DBMS,因此所有实体(表)都由一个列关联。

            EMPLOYEE - EMPID EMPNAME DEPTID

            部门 - 部门名称

            DEPTID 是 EMPLOYEE 表中的外键和 DEPARTMENT 表中的主键。

            这种关系是对象的虚构关系,只是一种考虑或一种设计,用于以一种易于将来检索的方式来结构化数据。不是物理关系(因为它是一种编程语言)

            为了检索该数据,我们需要很少的语法,并由 SQL 的创建者描述。

            从员工中选择 *

            从部门中选择 *

            SELECT * FROM EMPLOYEE WHERE DEPTID = 5

            为了方便起见,我们在这里虚构了两个表格,但为了获得所需的结果,我们使用了这种语法 WHERE DEPTID = 5。

            【讨论】:

            • 我猜你得到了 -1,因为你写的东西没有任何意义,也没有回答为什么要使用外键的问题。
            【解决方案8】:

            RESTRICT 运算符 (WHERE) 与引用约束无关!

            引用 C.J. Date 的 Relational Database Dictionary

            外键R1R2为relvars,不一定不同,让K为key对于 R1。让 FK 成为 R2 的标题的子集,这样就存在一个可能为空的属性重命名序列,将 K 映射到 K '(比如),其中 K'FK 包含完全相同的属性。那么FK就是外键

            引用完整性 松散地说,如果相应的引用元组不存在,则不允许引用元组存在的规则。更准确地说,让 FK 成为某个引用 relvar R2 中的某个外键;令 K 为对应引用的 relvar R1 中的对应键,令 K' 派生自 K 为在外键下描述。然后参照完整性规则要求在 R2 中永远不会存在不是 K' 值的 FK 值对于当时有问题的 R1 中的一些(必然是唯一的)元组。这里的R1R2分别是被引用的relvar和被引用的relvar,它们之间的约束是一个引用约束。

            示例:在 relvar SP 中,{S#}{P#} 是分别对应于 relvar S 和 P 中的键 {S#}{P#} 的外键。请注意,与给定外键对应的引用 relvar 中的键不需要是特定的主键。

            【讨论】:

              【解决方案9】:

              我有另一个很好的理由将关键关系添加到您的数据库中。有各种代码生成器使用此信息从您的数据库生成对象模型。一种值得注意的常用模式是 ActiveRecord 模式。如果没有键关系,ActiveRecord 模式将不知道您的数据库实体是如何相关的,因此它会生成一个不太有用的对象模型。

              代码生成并不适合每个软件项目。但是,它对大量项目很有帮助。如果您不使用代码生成,那么您至少应该对它进行研究。

              【讨论】:

              • 这正是我正在处理的问题。我从生产数据库自动生成了我的模型,并注意到数据库几乎没有使用外键。虽然使用 AR 查询映射表并非不可能。这无疑使得将 FK 与各自的 PK 联系起来变得不那么明显。很好的答案。
              【解决方案10】:

              FOREIGN KEY 约束用于防止破坏表之间链接的操作。

              FOREIGN KEY 约束还可以防止将无效数据插入外键列,因为它必须是它指向的表中包含的值之一。

              【讨论】:

                猜你喜欢
                • 2012-08-03
                • 2021-01-14
                • 1970-01-01
                • 2023-03-05
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-10-01
                相关资源
                最近更新 更多