我的理解:
除了对被引用表的有效引用之外,还允许具有外键的列包含 NULL 值。SQL 标准为外键定义了几种匹配模式,例如 MATCH SIMPLE 和 MATCH FULL。对于多列外键,只要外键的至少一列包含 NULL 值,MATCH SIMPLE 就允许任何列中存在错误(= 不引用)值。
多列外键很少见(因为多列主键是),但我可以想象有效的用例。例如,博客文章的翻译可能有一个主键(post_id, language_id)
。现在,引用此类翻译的内容(例如用户当前正在编辑的翻译)将具有多列外键。
我不明白的是:
为什么我会使用 MATCH SIMPLE 作为我的外键?
在上面的示例中,有一个仅引用 bypost_id
而不是 by的“当前正在编辑”条目是没有意义的language_id
。
什么是有意义的例子?
我的偏好是避免在外键列中出现空值。使所有外键不可为空。事实上,在我用于验证数据库设计的一些静态分析脚本中,我有外键 = not null 作为标准检查。
FULL / SIMPLE 行为非常模糊,以我的经验,即使专家也不总是能理解它(我是专家,我必须三思而后行!)正如 ypercube 指出的那样,SIMPLE 实际上是 Microsoft SQL Server 中的默认设置但我怀疑大多数使用该产品的人甚至从未考虑过它。如果您在数据库设计中的目标之一是使数据能够被普通用户理解和使用,那么外键应该是不可为空的。
不完全是。
NULL
如果行具有值,则所有外键约束都允许行“错误”(不引用) 。MATCH FULL
例如将允许(NULL, NULL)
两列外键中的一行。这对我来说也没有多大意义。唯一的区别是 - 正如你所提到的 - 这MATCH SIMPLE
将允许(post_id_value, NULL)
,(NULL, language_id_value)
rows 而MATCH FULL
不会。我在网站上看到了一些问题,其中
MATCH SIMPLE
一个值是空的(有些)是有意义的。这些案例通常有一些非规范化的设计。在您的示例中,它看起来像是历史表中的一个额外外键,仅使用两列之一:这将允许历史表在两个值都不为空时引用翻译表,而当 language_id 为空时引用后表。我自己从来不会使用它,但我见过它。
现在,抛开这些奇怪的情况,如果所有列都用 定义,则两个选项 (
MATCH FULL
和) 是相同的。而且由于通常在外键中有不可为空的列,并且此设置仅影响多列外键,我想这就是为什么许多设计人员通常不担心此设置并将其保留为 DBMS 的默认设置(在 Postgres 中) .MATCH SIMPLE
NOT NULL
MATCH SIMPLE
所以,对于你的问题:
我可以反问:
另请注意,大多数 DBMS 并未实现 SQL 标准提供的所有选项。Postgres 没有
MATCH PARTIAL
,SQL Server 根本没有选项(所有外键都表现为MATCH SIMPLE
)。你在问:
这是一个非常简单的例子:
在此示例中,该表
info
维护有关学生、课程和考试的信息,我们希望这些信息保持一致。没有match simple
这个是不可能的。请注意,但是会检查外键:最后,请注意,在上面的示例中,您必须至少指定一个学生或一门课程;