In some cases, it is interesting to create a conditional foreign key reference , that is, it does not allow you to reference all the records in another table, but only those that assume a condition.
For example: If you have a people table that stores both clients and vendors (accept "C" or "F" in the "people_type" column). Imagine a sales table could only refer people who are customers but not suppliers. What is the best way to create this restriction?
One possible way (I do not know if the best) would be to create an additional column and a compound reference, as in the example below:CREATE TABLE posts(
id INTEGER PRIMARY KEY,
title VARCHAR(255) NOT NULL,
accepts_comments BOOLEAN NOT NULL,
UNIQUE (id, accepts_comments)
);
CREATE TABLE comments(
id INTEGER PRIMARY KEY,
post_id INTEGER NOT NULL,
text VARCHAR(255) NOT NULL,
accepts_comments BOOLEAN NOT NULL DEFAULT (true) CHECK (accepts_comments = true),
FOREIGN KEY (post_id, accepts_comments) REFERENCES posts (id, accepts_comments)
);
INSERT INTO posts (id, title, accepts_comments) VALUES (1, 'aceita', true);
INSERT INTO posts (id, title, accepts_comments) VALUES (2, 'não aceita', false);
-- a parte interessante
-- ok
INSERT INTO comments (id, post_id, text)
VALUES (1, 1, 'aceita');
-- erro de chave estrangeira violada
INSERT INTO comments (id, post_id, text)
VALUES (2, 2, 'não aceita');
-- erro da constraint check
INSERT INTO comments (id, post_id, text, accepts_comments)
VALUES (3, 2, 'não aceita valor diferente', false);
The goal is to prevent comments on marked posts from permitting them.
Is this the right way to do this, or is there a more elegant way?