Answers:
共有三种匹配类型:
MATCH FULL
,MATCH PARTIAL
和MATCH SIMPLE
(默认设置)。MATCH FULL
除非所有外键列都为空,否则不允许多列外键的一列为空;如果它们全为空,则不需要该行在引用表中具有匹配项。MATCH SIMPLE
允许任何外键列为空;如果它们中的任何一个为null,则不需要该行在引用表中具有匹配项。MATCH PARTIAL
尚未实施。(当然,NOT NULL
可以将约束条件应用于引用列,以防止出现这些情况。)
通常,如果引用行的任何引用列为null,则不必满足外键约束。如果
MATCH FULL
将if 添加到外键声明中,则仅当其所有引用列均为null时,引用行才能满足约束条件(因此,确保null和non-null值的混合可确保MATCH FULL
约束失败)。如果您不希望引用行能够避免满足外键约束,则将引用列声明为NOT NULL
。
并且确保查阅当前手册或与您的安装相匹配的版本。不要因为过时的Google链接而过时了。
FULL
vs SIMPLE
vsPARTIAL
尽管选择的答案是正确的,但是如果这是您的新手,您可能希望通过代码查看它-我认为以这种方式更容易。
-- one row with (1,1)
CREATE TABLE foo ( a int, b int,
PRIMARY KEY (a,b)
);
INSERT INTO foo (a,b) VALUES (1,1);
--
-- two child tables to reference it
--
CREATE TABLE t_full ( a int, b int,
FOREIGN KEY (a,b) REFERENCES foo MATCH FULL
);
CREATE TABLE t_simple ( a int, b int,
FOREIGN KEY (a,b) REFERENCES foo MATCH SIMPLE
);
从逻辑上讲,使用FULL
和SIMPLE
可以插入完全匹配项。
-- works
INSERT INTO t_full (a,b) VALUES (1,1);
INSERT INTO t_simple (a,b) VALUES (1,1);
当列之一是时,问题就来了NULL
。
-- works
INSERT INTO t_simple (a,b) VALUES (1,NULL);
-- fails
INSERT INTO t_full (a,b) VALUES (1,NULL);
插入会t_full
产生以下错误,
ERROR: insert or update on table "t_full" violates foreign key constraint "t_full_a_fkey"
DETAIL: MATCH FULL does not allow mixing of null and nonnull key values.
INSERT 0 1
好的,那又如何(42,NULL)
-这是我经常感到困惑的部分MATCH SIMPLE
,
-- works
INSERT INTO t_simple (a,b) VALUES (42,NULL);
上述行为将不工作,未实现的MATCH PARTIAL
,这可能是你想要什么,其中最右边的列是一个复合索引NULL
编出来。但是,有些人认为这是将潘多拉盒子打开到不良设计的一种方法。
MATCH FULL
一切都必须完全匹配,或者所有列都必须是NULL
MATCH SIMPLE
如果有一件事是NULL
在约束简单地忽略。MATCH PARTIAL
如果NULL
事实是并非所有事情都可以通过为约束的目的而做一些明智的事情而NULL
得到部分挽救。为了后代,以下是SQL规范中有关 <match type>
MATCH SIMPLE
如果至少一个引用列为null,则引用表的行通过约束检查。如果所有引用列都不为空,则当且仅当所引用表的行与所有引用列匹配时,该行才通过约束检查。MATCH PARTIAL
:如果所有引用列均为null,则引用表的行通过约束检查。如果至少一个引用列不为空,则该行通过约束检查,并且仅当被引用表中的行与所有非空引用列匹配时才行。MATCH FULL
:如果所有引用列均为null,则引用表的行通过约束检查。如果所有引用列都不为空,则当且仅当所引用表的行与所有引用列匹配时,该行才通过约束检查。如果某个引用列为null,而另一个引用列为非null,则引用表的行违反了约束检查。
虽然这不是特定于PostgreSQL的,但这些示例已通过PostgreSQL进行了演示。