I'm asking this question to check if my reasoning about cascaded delete is correct and if I'm not overlooking anything. I understand the behavior and I'm not asking why it is implemented with the current restrictions.
When we try to create a table containing a self reference like this:
CREATE TABLE [BlogComments] (
[Id] int NOT NULL IDENTITY,
[AuthorName] nvarchar(100) NULL,
[Content] nvarchar(max) NULL,
[CreatedTime] datetime2 NOT NULL,
[ReplyToId] int NULL,
CONSTRAINT [PK_BlogComments] PRIMARY KEY ([Id]),
CONSTRAINT [FK_BlogComments_BlogComments_ReplyToId] FOREIGN KEY ([ReplyToId])
REFERENCES [BlogComments] ([Id]) ON DELETE SET NULL -- Not: CASCADE
);
We get the infamous exception
Introducing FOREIGN KEY constraint 'FK_BlogComments_BlogComments_ReplyToId' on table 'BlogComments' may cause cycles or multiple cascade paths.
I understand that the setting ON DELETE SET CASCADE
may actually cause a recursive cascade of deletes and, hence, may be dangerous, or time consuming at best. But ON DELETE SET NULL
is different: it will only nullify ReplyToId
of direct child records, not of their child records.
So am I right in concluding that SQL Server is overly restrictive when the foreign key is defined with ON DELETE SET NULL
? Or am I overlooking some good reasons for this restriction in this particular case?
By the way, I'm aware of a school of thought that contends that there shouldn't be any cascade actions anyway. Let's not get into that.
Best Answer
From Error message 1785 occurs when you create a FOREIGN KEY constraint that may cause multiple cascade paths
If a self reference with
on delete set null
was allowed by SQL Server the query plan need to have two different operator that changes the same table. First one that deletes the rows, store the deleted rows in a spool and the uses that spool to find the rows that needs to be updated. If you have a row whereReplyId
andId
is the same it will try to update the value of a row that is already deleted. Or at least it will be once the transaction is committed.I don't say it is impossible to implement this only that it is a lot more complicated than one might think at first sight. Think about how to handle halloween protection and add triggers and indexed views to the mix and it quickly goes into something not trivial to build the plan that does the job transactionally correct.