MATCH FULL、MATCH SIMPLE 和 MATCH PARTIAL 之间的区别?

46 postgresql foreign-key constraint referential-integrity ddl

我注意到了MATCH SIMPLEMATCH FULL,但我不明白它们是做什么的。我看到默认是MATCH SIMPLE; 但是,约束函数的其他MATCH子句如何FOREIGN KEY

Erw*_*ter 55

检查CREATE TABLE手册页

共有三种匹配类型:MATCH FULLMATCH PARTIALMATCH SIMPLE (这是默认值)。MATCH FULL除非所有外键列都为空,否则不允许多列外键的一列为空;如果它们都为空,则该行不需要在引用的表中具有匹配项。MATCH SIMPLE允许任何外键列为空;如果它们中的任何一个为空,则该行不需要在引用的表中具有匹配项。MATCH PARTIAL尚未实施。(当然,NOT NULL可以对引用列应用约束以防止出现这些情况。)

另外,在有关外键章节中

通常,如果引用行的任何引用列为空,则引用行不需要满足外键约束。如果MATCH FULL 添加到外键声明中,则仅当引用行的所有引用列都为空时,引用行才会满足约束条件(因此,空值和非空值的混合保证使MATCH FULL 约束失败)。如果您不希望引用行避免满足外键约束,请将引用列声明为NOT NULL.

并确保查阅当前手册或与您的安装匹配的版本。不要被过时的谷歌链接指向过时的版本。


Eva*_*oll 23

FULL对比SIMPLE对比PARTIAL

虽然选择的答案是正确的,但如果这对您来说是新的,您可能希望通过代码查看它——我认为这样更容易理解。

-- 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
);
Run Code Online (Sandbox Code Playgroud)

从逻辑上讲,使用FULLand SIMPLE,我们可以插入一个完整的匹配项。

-- works
INSERT INTO t_full (a,b) VALUES (1,1);
INSERT INTO t_simple (a,b) VALUES (1,1);
Run Code Online (Sandbox Code Playgroud)

当其中一列是NULL.

-- works
INSERT INTO t_simple (a,b) VALUES (1,NULL);

-- fails
INSERT INTO t_full (a,b) VALUES (1,NULL);
Run Code Online (Sandbox Code Playgroud)

插入到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
Run Code Online (Sandbox Code Playgroud)

好的,那怎么办(42,NULL)——这是我一直觉得困惑的部分MATCH SIMPLE

-- works
INSERT INTO t_simple (a,b) VALUES (42,NULL);
Run Code Online (Sandbox Code Playgroud)

上述行为将工作,未实现的MATCH PARTIAL,这可能是你想要什么,其中最右边的列是一个复合索引NULL编出来。然而,有些人认为这是打开潘多拉魔盒接受糟糕设计的一种方法。

简单定义和助记符

  • MATCH FULL一切都必须完全匹配,或者所有列都必须是NULL
  • MATCH SIMPLE如果一件事是NULL约束被简单地忽略。
  • MATCH PARTIAL如果有一件事是NULL事实,不是一切都NULL部分地通过做一些合理的约束的目的打捞上岸。

SQL 规范说明

对于后代,这里是 SQL 规范中的定义 <match type>

  • MATCH SIMPLE如果至少一个引用列为空,则引用表的行通过约束检查。如果所有引用列都不为空,则当且仅当引用表中存在与所有引用列匹配的行时,该行才会通过约束检查。
  • MATCH PARTIAL: 如果所有引用列都为空,则引用表的行通过约束检查。如果至少一个引用列不为空,则当且仅当引用表的一行与所有非空引用列匹配时,该行才通过约束检查。
  • MATCH FULL: 如果所有引用列都为空,则引用表的行通过约束检查。如果所有引用列都不为空,则当且仅当引用表中存在与所有引用列匹配的行时,该行才会通过约束检查。如果某个引用列为空而另一个引用列非空,则引用表的行违反约束检查。

虽然这不是 PostgreSQL 特定的,但这些示例是用 PostgreSQL 演示的

  • 这个例子其实就完成了欧文给出的解释!就我而言,我不太了解 Erwin,但我确实了解提供的示例。显然,Match Simple、Full、Partial 对涉及一列且仅一列的外键没有任何意义,对吗? (2认同)