4
In some cases, it is interesting to create a foreign key reference conditional, that is, that does not allow to reference all the records of another table, but only those that assume a condition.
For example: If you have a table people which stores both customers and suppliers (accepts "C" or "F" in the "person type" column). Imagine a sales chart could only reference people who are customers but not suppliers. What is the best way to create this restriction?
A possible way (I don’t know if the best one) would be to create an additional column and a composite 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 posts marked to not allow them.
Is this the right way to do it, or is there a more elegant way?
What if using a Procedure for insertion is not feasible? If I use an ORM, for example. I wish I had direct access to the chart, but with the restriction working somehow. However I understand that your proposal is feasible if I write all the SQL in the nail.
– user18284
Then you raise a
trigger
which makes the same check as theprocedure
makes. You need the code?– Leonel Sanches da Silva