Why am I getting "multiple cascade paths" with this table relationship? - sql

I have the following table relationship in my database:
Parent
/ \
Child1 Child2
\ /
GrandChild
I am trying to create the FK relationships so that the deletion of the Parent table cascades to both child and the grandchild table. For any one particular granchild, it will either be parented to one or the other child tables, but never both at the same time.
When I'm trying to add ON DELETE CASCADE to the FK relationships, everything is fine adding them to one "side" of the two children (Parent-Child1-GrandChild is fine for Cascade Delete). However, as soon as I add the Cascade Delete on the Child2 "side" of the relationship SQL tells me that the FK would cause multiple cascade paths. I was under the impression that multiple cascade paths only apply when more than one FK indicates the SAME table. Why would I be getting the multiple cascade paths error in this case?
PS The table relationships at this point would be very difficult to change so simply telling me to change my table structure is not going to be helpful, thanks.

The message means that if you delete a Parent record, there are two paths that lead to all deletable GrandChild records.
Fix: Remove the ON DELETE CASCADE options in the FKs, and create INSTEAD OF DELETE triggers for the ChildX tables, deleting all grandchild records, and then the childX records themselves.

Related

Why is ON DELETE CASCADE declared on child tables instead of their parent?

If a parent table has multiple child tables, wouldn't it make more sense to declare ON DELETE CASCADE on the parent table? This way, it wouldn't be necessary to add ON DELETE CASCADE on each of the child tables.
First -- and obviously -- you might not want on delete cascade on all foreign key relationships. Each foreign key can have its own behavior, which is defined where the foreign key is defined.
Also very important. The deletion behavior is assigned on the attribute associated with the table where the deletion is going to occur. That is much more in the spirit of SQL -- and sanity -- than having a master table decide to just delete records in a bunch of other tables.

How can these constraints may cause cycles or multiple cascade paths?

Note: this question is more about database design and SQL Server than specific ORMDB like EF Core.
I have a database schema that looks like this:
Using EF Core Migration, all the SQL statements can be run until the very last constraint (FK_BookReleases_Nicknames_NicknameId). The previous FK FK_BookReleases_Books_BookId could be added.
The error I receive is (as many other articles on SO):
Introducing FOREIGN KEY constraint
'FK_BookReleases_Nicknames_NicknameId' on table 'BookReleases' may
cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or
ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
My question is, where is the flaw on that design? I cannot understand under any logic such situation happens. And what is the proper fix? I see many suggested changing ON DELETE action but not specific on which FK and what other action I should use.
Worse, even already read this article I still don't understand how it could be a problem, and how would his proposed solution fits in the above schema.
The issue is due to multiple cascading paths from Author (Grand Parent) to BookRelease (Grand Child). There are two cascading paths:
Author -> Book -> BookRelease
Author -> Nickname -> BookRelease
This is discussed in detail in the post in MSSQLTips
So, the way to handle this is:
Disable the ON DELETE CASCAE and choose NOACTION as the foreign key creation.
Create INSTEAD OF DELETE TRIGGERS in Author(GrandParent), Book(Child1), Nickname(Child2) tables to handle the deletion of parent keys in the child tables.
Grand Parent deletion : Delete in GrandChild, followed by Child1,
followed by Child2,
Child1 deletion: Delete in GrandChild, followed
by Child1
Child2 deletion: Delete in GrandChild, followed by Child2

Delete records from relational database with no cascade involved

I need to delete records from relational database, where I attempt to start from the lowest children in the database.
I'm not very strong on how to approach the task. I don't want to do CASCADE delete, I actually want to do the opposite of CASCADE.
Is is correct that I have to find the entity that does not have child and start deleting the records there? and what if an entity has more that one foreign key, how do I decide on which parent table should I start to delete from?
You have to delete the child records first. If you try to delete a record that is referenced with a foreign key, you will get an error which should indicate which key has a conflict. You can then see which child table is impacted and delete the records that are referencing the foreign key, then try again.
You simply work your way up the chain. If more than one child record references a parent record, you simply delete all the child records first. If more than one parent record is referenced by a child record, it doesn't matter which parent is deleted first (or if they are deleted at all).
You don't give what database and what tools you have at hand.
You could manually diagram the database based on foreign keys or you could use a tool, such as visual studios to diagram your database.
As long as the multiple foreign relationships don't depend on one another it shouldn't matter where you start.

PostgreSQL delete from parent table only

I have a table structure with partitioned tables, where a few child tables inherit from a common parent. How so I DELETE only from the parent table?
Long story short, I ended up with some data in the parent table, and this should've never happened but now I have to clean up the mess.
You can specify that only parent table matters, simply by using keyword 'ONLY':
DELETE FROM ONLY parent_table_name;
See: http://www.postgresql.org/docs/current/static/sql-delete.html

Does DELETE CASCADE Option for Foreign Keys delete grandchildren?

pretty new to SQL cascading delete. I was wondering how cascade delete works when it comes the children. So say I have a table situation like:
ParentTable ==Cascade==> ChildTable ==NoCascade==> GrandChildTable
Will the grandchild also be deleted? Do I need to specify in the childtable to turn off cascade delete? I am using Fluent API to set the cascade delete for the parent ParentTable to the ChildTable with WillCascadeOnDelete(true), should I set WillCascadeOnDelete(false) on the ChildTable, is this necessary? The reason I can not delete the GrandChildTable is because it is a domain table.
Thanks,
Matt
Will the grandchild also be deleted?
No, not if your database system is not completely buggy, or lets say incompletely implemented (and this has not much to do with entity framework). If that would be possible, you could easily destroy data integrity against the intentions of those foreign key constraints.
If you want grandchilds to be deleted when a child gets deleted, you need an additional DELETE CASCADE constraint on the FK relation from ChildTable to GrandChildTable. It does not matter if the DELETE operation on the child comes from an explicit DELETE for that child, or from a cascading delete for the parent.