由于我可以在不使用关系密钥(主键和外键)的情况下连接两个表,因此首先定义这些键的目的是什么?
例如,我的第一张表是
customer table
fields are cust_id, lastname, firstname
我的第二张桌子是
product table
fields are product_id, productno, cust_id
即使我没有将任何字段声明为主键或foriegn键,我仍然可以加入这两个表:
SELECT *
FROM customer c
LEFT OUTER JOIN product p ON p.custid=c.cust_id
为什么我要定义键呢?
答案 0 :(得分:5)
有一些很好的答案,请允许我稍微推断一下。
正如“dasblinkenlight”所述,检索的速度(数据库事先知道两个表之间的关系,并可能潜在地优化查询),更重要的是,参考/数据完整性。
让我们再讨论第二个问题。
考虑一个简单的场景,你有以下三个表(我简化了这一点。实际上,你可以订购许多产品,但为了简洁,我保持简单):
CustomerTable
ID
FirstName
LastName
OrderTable
ID
CustomerID
ProductID
ProductTable
ID
Description
没有外键,我们可以自由地:
这是灾难的秘诀
通过使用外键,我们可以重新设计上述内容,因此:
CustomerTable
ID
FirstName
LastName
OrderTable
ID
CustomerID -> References CustomerTable.ID
ProductID -> References ProductTable.ID
ProductTable
ID
Description
我们可以指定CustomerID和ProductID是“NOT NULL”(就像其他列一样)。这意味着要创建订单,我们拥有以拥有现有客户和现有产品。优良!
但它变得更好。如果我开始删除产品会怎样?除非我们已经指定了一些级联选项(参见this),否则数据库会摇摇晃晃地说“Nope。你不能删除它,它被某些东西引用”。
这是等式的数据完整性部分。我们不能指出那些不存在的东西(外键坚持我们指出它什么都没有[如果允许空值],或者那里有什么东西。主键有助于我们这样做。)
突然之间,数据库本身确保一切都能很好地协同工作并且很好地结合在一起。没有它,你可以删除所有订单...删除产品...删除你想要的任何东西,然后你的应用程序会想知道到底是怎么回事。
使用它们:)
答案 1 :(得分:3)
告诉你的RDBMS两个密钥相关的两个原因是
除此之外,可以以类似的方式使用密钥和非密钥字段。特别是,加入未声明为主键或外键的列肯定是可以的。
答案 2 :(得分:3)
这不是关于“能够加入”它是关于允许进入表格的内容。此外,如果删除客户会发生什么,但数据库中有未完成的产品?如果没有外键,它们就是所谓的孤立记录。添加外键,默认情况下会阻止删除子表引用的对象。
答案 3 :(得分:2)
这些概念都与约束有关。
PRIMARY KEY
是一个约束,表示一组列是唯一的,而不是NULL
。大多数实现使用索引来支持这一点,在某些实现中,主键也是用于对磁盘存储中的页面中的数据进行排序的集群索引。
FOREIGN KEY
是一个约束,表示一组列引用另一个表中的另一组列。通常,外键仍然可以是NULL
,但如果它不是NULL
,那么它必须是它引用的表中的有效键,并且也必须是唯一的。它引用的密钥不必是PRIMARY KEY,只是一个唯一的密钥(数据库通常通过约束来确定它,如唯一约束或索引)。外键本身不必具有索引,但这通常是个好主意,因为删除所引用的表中的行需要在允许删除之前检查所有外键。这些都属于参照完整性的概念。
通常,对数据库的所有约束都会保护数据完整性,并允许优化器了解限制并获得有关最佳执行计划的更多线索。但是,可以简单地在表上具有适当的唯一索引,并且仍然可以获得相同的执行计划,而不将索引作为主键的一部分或作为定义外键引用的前提,但索引是独特肯定会影响计划的选择。
查询中有许多允许(DML),但DDL声明了数据的结构。
答案 4 :(得分:1)
简短回答,数据完整性。
同样使用这样的外键将确保搜索发生得更快,因为更多数据输入到表中。
答案 5 :(得分:0)
连接仅用于“公共变量”,因此连接可用于连接两个表中具有相等值的表。主键必须是唯一的,因此您始终可以引用它们,因此您也可以将它们用作其他表的引用。基本上当你从2个表中进行查询时,发生的事情是笛卡尔积。 (这不是在实际实现中发生的,因为时间是一个因素)并且这会产生大量数据,但是连接会减少结果中的数据(理论上)。 你可以在这里阅读更多关于加入的内容: