Can a Foreign key be NULL?
Existing answers focused on single column scenario. If we consider multi column foreign key we have more options using MATCH [SIMPLE | PARTIAL | FULL] clause defined in SQL Standard:
PostgreSQL-CREATE TABLE
A value inserted into the referencing column(s) is matched against the values of the referenced table and referenced columns using the given match type. There are three match types: MATCH FULL, MATCH PARTIAL, and MATCH 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.)
Example:
CREATE TABLE A(a VARCHAR(10), b VARCHAR(10), d DATE , UNIQUE(a,b)); INSERT INTO A(a, b, d) VALUES (NULL, NULL, NOW()),('a', NULL, NOW()),(NULL, 'b', NOW()),('c', 'b', NOW()); CREATE TABLE B(id INT PRIMARY KEY, ref_a VARCHAR(10), ref_b VARCHAR(10)); -- MATCH SIMPLE - default behaviour nulls are allowed ALTER TABLE B ADD CONSTRAINT B_Fk FOREIGN KEY (ref_a, ref_b) REFERENCES A(a,b) MATCH SIMPLE; INSERT INTO B(id, ref_a, ref_b) VALUES (1, NULL, 'b'); -- (NULL/'x') 'x' value does not exists in A table, but insert is valid INSERT INTO B(id, ref_a, ref_b) VALUES (2, NULL, 'x'); ALTER TABLE B DROP CONSTRAINT IF EXISTS B_Fk; -- cleanup -- MATCH PARTIAL - not implemented ALTER TABLE B ADD CONSTRAINT B_Fk FOREIGN KEY (ref_a, ref_b) REFERENCES A(a,b) MATCH PARTIAL; -- ERROR: MATCH PARTIAL not yet implemented DELETE FROM B; ALTER TABLE B DROP CONSTRAINT IF EXISTS B_Fk; -- cleanup -- MATCH FULL nulls are not allowed ALTER TABLE B ADD CONSTRAINT B_Fk FOREIGN KEY (ref_a, ref_b) REFERENCES A(a,b) MATCH FULL; -- FK is defined, inserting NULL as part of FK INSERT INTO B(id, ref_a, ref_b) VALUES (1, NULL, 'b'); -- ERROR: MATCH FULL does not allow mixing of null and nonnull key values. -- FK is defined, inserting all NULLs - valid INSERT INTO B(id, ref_a, ref_b) VALUES (1, NULL, NULL);
db<>fiddle demo