0

Scenario

Imagine a chat server with conversations C and multiple posts P in each conversation. A user can reply to a post. This data should be stored as reply := (original_post_id, replyer_post_id).

To mimic this I have the tables P (posts) and R (replies):

CREATE TABLE P (
    id BIGINT NOT NULL,
    -- more data ...
)

CREATE TABLE R (
    orig_id BIGINT NOT NULL,
    repl_id BIGINT NOT NULL,

    FOREIGN KEY orig_id REFERENCES P(id),
    FOREIGN KEY repl_id REFERENCES P(id),
)


Problem

If I want to automaically delete all associated R-entries upon deletion inside P, I would change the last two lines of R's definition to:

    ...
    FOREIGN KEY orig_id REFERENCES P(id) ON DELETE CASCADE,
    FOREIGN KEY repl_id REFERENCES P(id) ON DELETE CASCADE,
)

However, I recieve the following error:

Introducing FOREIGN KEY constraint [...] on table [...] may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.


Question

Why exactly am I recieving this error? Technically it is not a cycle as neither R.orig_id nor R.repl_id are referenced by any other table (thus possbibly creating a cycle). I furthermore cannot see why multiple cascade paths should be an issue, as the deletion procedure would be as follows:

  • Delete an entry from P with P.id = 1234
  • Delete any entry from R with R.repl_id = 1234 or R.orig_id = 1234

Should I somehow constrain the columns R.repl_id and R.orig_id not to be equal?

unknown6656
  • 2,765
  • 2
  • 36
  • 52
  • https://stackoverflow.com/a/852047/575376 – juergen d Dec 30 '18 at 09:43
  • I also don't see an issue with cycles, but I do see multiple cascade paths. Why do you have two foreign keys pointing to the same primary key? I think the easy fix here is to just maintain a single foreign key. – Tim Biegeleisen Dec 30 '18 at 09:44
  • Well, a reply is a post (identified by its ID) on an other post (also by its ID). A valid reply would only be a tuple of two valid post IDs (both being represented by `P.id`). – unknown6656 Dec 30 '18 at 09:51
  • 2
    Table `R` lets you tie together _any_ pairs of posts in `P`. What happens when you have ( 1, 2 ) and ( 2, 1 )? Cycles like that could be arbitrarily long and branch into bizarre shapes. That may not be allowed in your application, but the database isn't "aware" of that. Since a post is presumably either independent or a reply to a _single_ post you could dispense with table `R` and add a `ReplyToPostId` column to `P` with a default value of `NULL`. – HABO Dec 30 '18 at 15:29
  • I think you have to adding Primary Key : PRIMARY KEY pk_r_table (orig_id, repl_id), – Sanpas Dec 31 '18 at 10:08
  • @HABO I don't see the problem with that: even if I had ( 1, 2 ) and ( 2, 1 ), whenever I delete any post (`P.id = 2`) I expect **all** the relationships where it's directly involved (`R.repl_id = 2` or `R.orig_id = 2`) to be deleted, it shouldn't lead to any cycles, as deleting rows in R doesn't affect P, but the other way around... I still don't understand this error – Xriuk Apr 14 '22 at 08:02

0 Answers0