How does ON DELETE CASCADE relate to JSON?
-
24-01-2021 - |
Question
For relational databases, there is the notion of ON DELETE CASCADE
. When working with JSON, how do these two concepts relate? Is ON DELETE CASCADE
supported for JSON?
Can you give an example of a JSON-DB which supports ON DELETE CASCADE
or allows some work around for that?
Solution
You're confused here,
- JSON is a data-interchange format, in PostgreSQL we provide
json
andjsonb
as formats with advantages like validation and indexing that help you work with this format. ON DELETE CASCADE
is a clause that tells a referring table what to do when the table that it refers to lose the row it's referencing.
You can mix the two concepts, but you should never do this
CREATE TABLE tfoo ( qux jsonb PRIMARY KEY );
CREATE TABLE tbar ( qux jsonb REFERENCES tfoo );
CREATE TABLE tbaz ( qux jsonb REFERENCES tfoo ON DELETE CASCADE );
Now we can insert some test data in tfoo
,
INSERT INTO tfoo (qux) VALUES ( '{"id":42}' );
INSERT INTO tfoo (qux) VALUES ( '{"id":7}' );
And you'll get a reject if you try to insert into tbar
or tbaz
anything but the above,
-- Rejection
INSERT INTO tbar (qux) VALUES ( '{"id":2}' );
ERROR: insert or update on table "tbar" violates foreign key constraint "tbar_qux_fkey"
DETAIL: Key (qux)=({"id": 2}) is not present in table "tfoo".
This is a really bad idea though for many reasons. We can see here that these work though,
INSERT INTO tbar (qux) VALUES ( '{"id":42}' ); -- ON DELETE REJECT
INSERT INTO tbaz (qux) VALUES ( '{"id":7}' ); -- ON DELETE CASCADE
And moreover, we can see the effects -- {"id":7}
is in tbaz
which has the ON DELETE CASCADE
DELETE FROM tfoo WHERE qux = '{"id":7}';
And, this fails as {"id":42}
is in tbar
and it doesn't know what to do if you remove that entry from tfoo
so it rejects the operation.
DELETE FROM tfoo WHERE qux = '{"id":42}';
ERROR: update or delete on table "tfoo" violates foreign key constraint "tbar_qux_fkey" on table "tbar"
DETAIL: Key (qux)=({"id": 42}) is still referenced from table "tbar".
Clarification
So you can see you can have ON DELETE CASCADE
on any type that can be put on a UNIQUE
index (PRIMARY KEY
is a special UNIQUE NOT NULL
index). This means, you can mix these two concepts, as we did above. But you should never do that, and I've never seen it done in practice. Generally, you put FOREIGN KEYS
on int
or text
,
CREATE TABLE tfoo (
id_foo int PRIMARY KEY
GENERATED BY DEFAULT AS IDENTITY,
qux jsonb
);
CREATE TABLE tbar ( id_foo REFERENCES tfoo, qux jsonb );
CREATE TABLE tbaz ( id_foo REFERENCES tfoo ON DELETE CASCADE, qux jsonb );
OTHER TIPS
Adding to Evan's explanation how it should not be done, here is why it should not be done, referring to CouchDB
:
https://stackoverflow.com/questions/1951030/does-couchdb-supports-referential-integrity
https://stackoverflow.com/questions/1197449/how-do-i-dry-up-my-couchdb-views