我对FOREIGN KEY和CHECK约束之间的区别感到困惑 - 他们似乎达到了相同的结果。检查和外键有什么区别?
我的意思是我可以创建一个表并在另一个表上强制执行一个外键,但是我可以创建一个CHECK来确保另一个表中的值。
有什么区别以及何时使用这个或那个?
我对FOREIGN KEY和CHECK约束之间的区别感到困惑 - 他们似乎达到了相同的结果。检查和外键有什么区别?
我的意思是我可以创建一个表并在另一个表上强制执行一个外键,但是我可以创建一个CHECK来确保另一个表中的值。
有什么区别以及何时使用这个或那个?
一个外键约束确保项不存在
编辑 另一个表
按照正确的注释存在于另一个表...或相同的表。 - Mark Byers
CHECK约束确保条目遵循一些规则。
CHECK约束通过限制由列接受的值执行域的完整性。它们与FOREIGN KEY约束类似,它们控制放在列中的值。 区别在于它们如何确定哪些值是有效的:FOREIGN KEY约束从另一个表中获取有效值的列表,并且CHECK约束根据不基于另一列中的数据的逻辑表达式确定有效值。
外键约束比CHECK约束更强大。
外键约束意味着列(在当前表中)只能具有已存在于外表列中的值(可能包括相同的表,通常是为分层数据完成的)。这意味着随着值列表的变化 - 变大或变小 - 不需要更新约束。
检查约束不能引用当前表之外的任何列,也不能包含子查询。通常,这些值是硬编码的,如BETWEEN 100 and 999
或IN (1, 2, 3)
。这意味着随着情况的变化,您必须每次更新CHECK约束。此外,外键关系在实体关系图(ERD)上可见,而CHECK约束永远不会。好处是有人可以读取ERD并从中构建查询,而无需使用大量的DESC表命令来知道哪些列是哪里以及哪些与构建适当的连接有关。
最佳做法是首先使用外键(和支持表)。使用CHECK约束作为不能使用外键的情况的备份,而不是验证数据的主要解决方案。
外键不必是单列键。 – 2010-04-11 18:04:04
它取决于您的DBMS(您没有指定),但从某种意义上说,您是正确的:外键约束是检查约束的特定情况。有数据库管理系统不允许你制定一个外键约束作为检查约束。
检查约束的主要目的是描述适用于表中单个行的条件。例如,我有一张元素表(如氢,氦,...),并且元素的符号被限制为以大写字母开头,并且后面跟着零个,一个或两个小写字母(两个小写字母,但尚未被发现但预测的元素:Uus - ununseptium(117) ,它刚刚被隔离但尚未命名)。这可以是一个CHECK约束的主题:
CHECK(Symbol MATCHES "[A-Z][a-z]{0,2}")
假设MATCHES存在并支持适当的正则表达式语言。
你也可以有一个比较值的检查约束:
CHECK(OrderDate <= ShipDate OR ShipDate IS NULL)
为了表达一个外键约束的检查约束,你要允许CHECK子句中执行查询。假设:
CHECK(EXISTS(SELECT * FROM SomeTable AS s
WHERE ThisTable.pk_col1 = s.pk_col1 AND
ThisTable.pk_col2 = s.pk_col2))
此示例显示了一些问题。我没有一个方便的表格别名,用于编写检查约束的表格 - 我认为它是'ThisTable'。构造是冗长的。假设在SomeTable主键的列pk_col1
和pk_col2
声明,那么外键子句是更加紧凑:
FOREIGN KEY (pk_col1, pk_col2) REFERENCES SomeTable
或者,如果你引用一个替代键,而不是主键:
FOREIGN KEY (pk_col1, pk_col2) REFERENCES SomeTable(ak_col1, ak_col2)
这在命名上更加紧凑 - 因此出错的可能性更小 - 并且可以由服务器进行特殊配置,因为特殊符号意味着它知道它正在处理外键约束,而通用检查子句必须仔细检查,看它是否符合许多可能的形式之一相当于外键。
问题问:何时使用检查约束以及何时使用外键约束?
存在于另一张桌子......或同一张桌子上。 – 2010-04-11 17:29:19
CHECK约束确定不基于另一列中的数据的...。 不太正确,检查约束可以包含多列(至少10g)。更好的是说“不是基于另一个表中的数据”。 – Juraj 2010-04-19 20:43:38