Differences between MATCH FULL, MATCH SIMPLE, and MATCH PARTIAL?
Check the CREATE TABLE
page of the manual:
There are three match types:
MATCH FULL
,MATCH PARTIAL
, andMATCH SIMPLE
(which is the default).MATCH FULL
will not allow one column of a multicolumn foreign key to be null unless all foreign key columns are null; if they are all null, the row is not required to have a match in the referenced table.MATCH SIMPLE
allows any of the foreign key columns to be null; if any of them are null, the row is not required to have a match in the referenced table.MATCH PARTIAL
is not yet implemented. (Of course,NOT NULL
constraints can be applied to the referencing column(s) to prevent these cases from arising.)
Also, in the chapter on Foreign Keys:
Normally, a referencing row need not satisfy the foreign key constraint if any of its referencing columns are null. If
MATCH FULL
is added to the foreign key declaration, a referencing row escapes satisfying the constraint only if all its referencing columns are null (so a mix of null and non-null values is guaranteed to fail aMATCH FULL
constraint). If you don't want referencing rows to be able to avoid satisfying the foreign key constraint, declare the referencing column(s) asNOT NULL
.
And be sure to consult the current manual or the version matching your installation. Don't fall for outdated Google links to outdated versions.
FULL
vs SIMPLE
vs PARTIAL
While the chosen answer is correct, if this is new to you, you may want to see it with code -- I think it's easier to grok that way.
-- 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
);
Logically, with FULL
and SIMPLE
, we can insert a full match.
-- works
INSERT INTO t_full (a,b) VALUES (1,1);
INSERT INTO t_simple (a,b) VALUES (1,1);
The problem comes when one of the columns is NULL
.
-- works
INSERT INTO t_simple (a,b) VALUES (1,NULL);
-- fails
INSERT INTO t_full (a,b) VALUES (1,NULL);
The insert into t_full
generates the following error,
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
Ok, so what about (42,NULL)
-- this is the part that I always found confusing about MATCH SIMPLE
,
-- works
INSERT INTO t_simple (a,b) VALUES (42,NULL);
The above behavior would NOT work with the unimplemented MATCH PARTIAL
, which likely does what you want for a compound index where the right-most column are NULL
ed out. However, some people view that as a method of opening up a Pandora's box to bad design.
Simple Definitions & Mnemonics
MATCH FULL
everything must fully match, or all columns must beNULL
MATCH SIMPLE
if one thing isNULL
the constraint is simply ignored.MATCH PARTIAL
if one thing isNULL
the fact that not everything isNULL
is partially salvaged by doing something sensible for the purpose of the constraint.
SQL Spec Notes
For posterity, here are the definitions from the SQL Spec on the <match type>
MATCH SIMPLE
if at least one referencing column is null, then the row of the referencing table passes the constraint check. If all referencing columns are not null, then the row passes the constraint check if and only if there is a row of the referenced table that matches all the referencing columns.MATCH PARTIAL
: if all referencing columns are null, then the row of the referencing table passes the constraint check. If at least one referencing columns is not null, then the row passes the constraint check if and only if there is a row of the referenced table that matches all the non-null referencing columns.MATCH FULL
: if all referencing columns are null, then the row of the referencing table passes the constraint check. If all referencing columns are not null, then the row passes the constraint check if and only if there is a row of the referenced table that matches all the referencing columns. If some referencing column is null and another referencing column is non-null, then the row of the referencing table violates the constraint check.
While this is not PostgreSQL specific these examples are demonstrated with PostgreSQL