Tables with mixed ON DELETE CASCADE and ON DELETE RESTRICT, rule set with recursion? The 2019...

Patience, young "Padovan"

How to change the limits of integration

Why isn't airport relocation done gradually?

Is bread bad for ducks?

What is the steepest angle that a canal can be traversable without locks?

Could JWST stay at L2 "forever"?

What tool would a Roman-age civilization have to grind silver and other metals into dust?

Why can Shazam do this?

Why is it "Tumoren" and not "Tumore"?

Why is my p-value correlated to difference between means in two sample tests?

How to create dashed lines/arrows in Illustrator

Springs with some finite mass

Inversion Puzzle

Is domain driven design an anti-SQL pattern?

Why Did Howard Stark Use All The Vibranium They Had On A Prototype Shield?

I looked up a future colleague on LinkedIn before I started a job. I told my colleague about it and he seemed surprised. Should I apologize?

Inflated grade on resume at previous job, might former employer tell new employer?

Is three citations per paragraph excessive for undergraduate research paper?

How can I create a character who can assume the widest possible range of creature sizes?

Dual Citizen. Exited the US on Italian passport recently

How to deal with fear of taking dependencies

Does a dangling wire really electrocute me if I'm standing in water?

Pristine Bit Checking

How can I fix this gap between bookcases I made?



Tables with mixed ON DELETE CASCADE and ON DELETE RESTRICT, rule set with recursion?



The 2019 Stack Overflow Developer Survey Results Are InReferential Integrity in schema, cascading the renamingCan I use `on delete set null` on a compound foreign key which contains a primary key column?Why can't we have multiple cascade paths?Several Foreign Key and Cascade Delete SQL ServerChanging Action on Delete to CascadeVisualize the effects of a cascading delete or update?Is there a possibility to see cascade path in MS SQLCycles or multiple cascade paths with on delete set null: really?Delete all records in tables with reference to another referenceHow to find out if entity is used in relations somewhere in database?





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ margin-bottom:0;
}







1















Not sure if this is a generic question, but unless not, this is MySQL 5.6.



We have a database consisting of ~300 tables, INNODB, all connected with proper foreign keys. One of these tables can be seen as the parent. My desired end result is that I can execute one delete on this table, and have all related information in all other 300 tables deleted as well.



However, the declared foreign keys are a mix of RESTRICT and CASCADE for ON DELETE and I'm trying to understand the rule set when these are applied in recursion.



I've been trying to find information on this, but no luck. Testing appears to indicate that RESTRICT blocks a CASCADE, but not necessarily. Consider this example:




Tables: A, B, C

B -> A (ON DELETE CASCADE)

C -> A (ON DELETE CASCADE)

C -> B (ON DELETE RESTRICT)




In this example, rows from B and C are deleted when A is deleted. However, since C -> B has a RESTRICT one could think that matching rows would block a CASCADE. But this is not the case. However, if I add an additional table D like this:




Tables: A, B, C, D

B -> A (ON DELETE CASCADE)

C -> A (ON DELETE CASCADE)

C -> B (ON DELETE RESTRICT)

D -> C (ON DELETE RESTRICT)




A delete from A is blocked by the RESTRICT from D to C.



A simple approach would be to simply use CASCADE everywhere, but I'm curious about the rule set. Or if the behaviour is either implementation dependent or simply undefined.



Is it based on level of depth of the CASCADING? That is, the shortest path determines the effective ON DELETE rule to use? What if multiple paths have the same length, with different rules?










share|improve this question














bumped to the homepage by Community 10 mins ago


This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
















  • Are you sure the case with 3 tables (A, B, C) succeeds always?

    – ypercubeᵀᴹ
    Mar 2 '18 at 14:08











  • dbfiddle.uk 3 cases, some fail, some succeed

    – ypercubeᵀᴹ
    Mar 2 '18 at 14:24











  • By 3 cases, are you talking about the 3 possible cases you can have with rows in this example? My assumption here was was 3 tables will all non-nullable fields, with rows that make use of the foreign keys.

    – Matthias
    Mar 2 '18 at 14:42











  • I'm trying to understand the general rule set though, without regard to the rows. On a logical level. Ultimately, I want to implement an algorithm that by just analysing the tables' structure can verify whether a delete will always be a success, or not (only succeeding under some conditions is a fail).

    – Matthias
    Mar 2 '18 at 14:44













  • Yes, with 3 cases I meant the specific inserts. Deleting aid=1 and aid=2 fail. Deleting aid=3 succeeds. The desgin is exactly as your question, 3 tables, not nullable columns, and FKs from (B->A, C->B, C->A).

    – ypercubeᵀᴹ
    Mar 2 '18 at 14:52


















1















Not sure if this is a generic question, but unless not, this is MySQL 5.6.



We have a database consisting of ~300 tables, INNODB, all connected with proper foreign keys. One of these tables can be seen as the parent. My desired end result is that I can execute one delete on this table, and have all related information in all other 300 tables deleted as well.



However, the declared foreign keys are a mix of RESTRICT and CASCADE for ON DELETE and I'm trying to understand the rule set when these are applied in recursion.



I've been trying to find information on this, but no luck. Testing appears to indicate that RESTRICT blocks a CASCADE, but not necessarily. Consider this example:




Tables: A, B, C

B -> A (ON DELETE CASCADE)

C -> A (ON DELETE CASCADE)

C -> B (ON DELETE RESTRICT)




In this example, rows from B and C are deleted when A is deleted. However, since C -> B has a RESTRICT one could think that matching rows would block a CASCADE. But this is not the case. However, if I add an additional table D like this:




Tables: A, B, C, D

B -> A (ON DELETE CASCADE)

C -> A (ON DELETE CASCADE)

C -> B (ON DELETE RESTRICT)

D -> C (ON DELETE RESTRICT)




A delete from A is blocked by the RESTRICT from D to C.



A simple approach would be to simply use CASCADE everywhere, but I'm curious about the rule set. Or if the behaviour is either implementation dependent or simply undefined.



Is it based on level of depth of the CASCADING? That is, the shortest path determines the effective ON DELETE rule to use? What if multiple paths have the same length, with different rules?










share|improve this question














bumped to the homepage by Community 10 mins ago


This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
















  • Are you sure the case with 3 tables (A, B, C) succeeds always?

    – ypercubeᵀᴹ
    Mar 2 '18 at 14:08











  • dbfiddle.uk 3 cases, some fail, some succeed

    – ypercubeᵀᴹ
    Mar 2 '18 at 14:24











  • By 3 cases, are you talking about the 3 possible cases you can have with rows in this example? My assumption here was was 3 tables will all non-nullable fields, with rows that make use of the foreign keys.

    – Matthias
    Mar 2 '18 at 14:42











  • I'm trying to understand the general rule set though, without regard to the rows. On a logical level. Ultimately, I want to implement an algorithm that by just analysing the tables' structure can verify whether a delete will always be a success, or not (only succeeding under some conditions is a fail).

    – Matthias
    Mar 2 '18 at 14:44













  • Yes, with 3 cases I meant the specific inserts. Deleting aid=1 and aid=2 fail. Deleting aid=3 succeeds. The desgin is exactly as your question, 3 tables, not nullable columns, and FKs from (B->A, C->B, C->A).

    – ypercubeᵀᴹ
    Mar 2 '18 at 14:52














1












1








1








Not sure if this is a generic question, but unless not, this is MySQL 5.6.



We have a database consisting of ~300 tables, INNODB, all connected with proper foreign keys. One of these tables can be seen as the parent. My desired end result is that I can execute one delete on this table, and have all related information in all other 300 tables deleted as well.



However, the declared foreign keys are a mix of RESTRICT and CASCADE for ON DELETE and I'm trying to understand the rule set when these are applied in recursion.



I've been trying to find information on this, but no luck. Testing appears to indicate that RESTRICT blocks a CASCADE, but not necessarily. Consider this example:




Tables: A, B, C

B -> A (ON DELETE CASCADE)

C -> A (ON DELETE CASCADE)

C -> B (ON DELETE RESTRICT)




In this example, rows from B and C are deleted when A is deleted. However, since C -> B has a RESTRICT one could think that matching rows would block a CASCADE. But this is not the case. However, if I add an additional table D like this:




Tables: A, B, C, D

B -> A (ON DELETE CASCADE)

C -> A (ON DELETE CASCADE)

C -> B (ON DELETE RESTRICT)

D -> C (ON DELETE RESTRICT)




A delete from A is blocked by the RESTRICT from D to C.



A simple approach would be to simply use CASCADE everywhere, but I'm curious about the rule set. Or if the behaviour is either implementation dependent or simply undefined.



Is it based on level of depth of the CASCADING? That is, the shortest path determines the effective ON DELETE rule to use? What if multiple paths have the same length, with different rules?










share|improve this question














Not sure if this is a generic question, but unless not, this is MySQL 5.6.



We have a database consisting of ~300 tables, INNODB, all connected with proper foreign keys. One of these tables can be seen as the parent. My desired end result is that I can execute one delete on this table, and have all related information in all other 300 tables deleted as well.



However, the declared foreign keys are a mix of RESTRICT and CASCADE for ON DELETE and I'm trying to understand the rule set when these are applied in recursion.



I've been trying to find information on this, but no luck. Testing appears to indicate that RESTRICT blocks a CASCADE, but not necessarily. Consider this example:




Tables: A, B, C

B -> A (ON DELETE CASCADE)

C -> A (ON DELETE CASCADE)

C -> B (ON DELETE RESTRICT)




In this example, rows from B and C are deleted when A is deleted. However, since C -> B has a RESTRICT one could think that matching rows would block a CASCADE. But this is not the case. However, if I add an additional table D like this:




Tables: A, B, C, D

B -> A (ON DELETE CASCADE)

C -> A (ON DELETE CASCADE)

C -> B (ON DELETE RESTRICT)

D -> C (ON DELETE RESTRICT)




A delete from A is blocked by the RESTRICT from D to C.



A simple approach would be to simply use CASCADE everywhere, but I'm curious about the rule set. Or if the behaviour is either implementation dependent or simply undefined.



Is it based on level of depth of the CASCADING? That is, the shortest path determines the effective ON DELETE rule to use? What if multiple paths have the same length, with different rules?







mysql delete recursive cascade






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Mar 1 '18 at 21:37









MatthiasMatthias

61




61





bumped to the homepage by Community 10 mins ago


This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.







bumped to the homepage by Community 10 mins ago


This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.















  • Are you sure the case with 3 tables (A, B, C) succeeds always?

    – ypercubeᵀᴹ
    Mar 2 '18 at 14:08











  • dbfiddle.uk 3 cases, some fail, some succeed

    – ypercubeᵀᴹ
    Mar 2 '18 at 14:24











  • By 3 cases, are you talking about the 3 possible cases you can have with rows in this example? My assumption here was was 3 tables will all non-nullable fields, with rows that make use of the foreign keys.

    – Matthias
    Mar 2 '18 at 14:42











  • I'm trying to understand the general rule set though, without regard to the rows. On a logical level. Ultimately, I want to implement an algorithm that by just analysing the tables' structure can verify whether a delete will always be a success, or not (only succeeding under some conditions is a fail).

    – Matthias
    Mar 2 '18 at 14:44













  • Yes, with 3 cases I meant the specific inserts. Deleting aid=1 and aid=2 fail. Deleting aid=3 succeeds. The desgin is exactly as your question, 3 tables, not nullable columns, and FKs from (B->A, C->B, C->A).

    – ypercubeᵀᴹ
    Mar 2 '18 at 14:52



















  • Are you sure the case with 3 tables (A, B, C) succeeds always?

    – ypercubeᵀᴹ
    Mar 2 '18 at 14:08











  • dbfiddle.uk 3 cases, some fail, some succeed

    – ypercubeᵀᴹ
    Mar 2 '18 at 14:24











  • By 3 cases, are you talking about the 3 possible cases you can have with rows in this example? My assumption here was was 3 tables will all non-nullable fields, with rows that make use of the foreign keys.

    – Matthias
    Mar 2 '18 at 14:42











  • I'm trying to understand the general rule set though, without regard to the rows. On a logical level. Ultimately, I want to implement an algorithm that by just analysing the tables' structure can verify whether a delete will always be a success, or not (only succeeding under some conditions is a fail).

    – Matthias
    Mar 2 '18 at 14:44













  • Yes, with 3 cases I meant the specific inserts. Deleting aid=1 and aid=2 fail. Deleting aid=3 succeeds. The desgin is exactly as your question, 3 tables, not nullable columns, and FKs from (B->A, C->B, C->A).

    – ypercubeᵀᴹ
    Mar 2 '18 at 14:52

















Are you sure the case with 3 tables (A, B, C) succeeds always?

– ypercubeᵀᴹ
Mar 2 '18 at 14:08





Are you sure the case with 3 tables (A, B, C) succeeds always?

– ypercubeᵀᴹ
Mar 2 '18 at 14:08













dbfiddle.uk 3 cases, some fail, some succeed

– ypercubeᵀᴹ
Mar 2 '18 at 14:24





dbfiddle.uk 3 cases, some fail, some succeed

– ypercubeᵀᴹ
Mar 2 '18 at 14:24













By 3 cases, are you talking about the 3 possible cases you can have with rows in this example? My assumption here was was 3 tables will all non-nullable fields, with rows that make use of the foreign keys.

– Matthias
Mar 2 '18 at 14:42





By 3 cases, are you talking about the 3 possible cases you can have with rows in this example? My assumption here was was 3 tables will all non-nullable fields, with rows that make use of the foreign keys.

– Matthias
Mar 2 '18 at 14:42













I'm trying to understand the general rule set though, without regard to the rows. On a logical level. Ultimately, I want to implement an algorithm that by just analysing the tables' structure can verify whether a delete will always be a success, or not (only succeeding under some conditions is a fail).

– Matthias
Mar 2 '18 at 14:44







I'm trying to understand the general rule set though, without regard to the rows. On a logical level. Ultimately, I want to implement an algorithm that by just analysing the tables' structure can verify whether a delete will always be a success, or not (only succeeding under some conditions is a fail).

– Matthias
Mar 2 '18 at 14:44















Yes, with 3 cases I meant the specific inserts. Deleting aid=1 and aid=2 fail. Deleting aid=3 succeeds. The desgin is exactly as your question, 3 tables, not nullable columns, and FKs from (B->A, C->B, C->A).

– ypercubeᵀᴹ
Mar 2 '18 at 14:52





Yes, with 3 cases I meant the specific inserts. Deleting aid=1 and aid=2 fail. Deleting aid=3 succeeds. The desgin is exactly as your question, 3 tables, not nullable columns, and FKs from (B->A, C->B, C->A).

– ypercubeᵀᴹ
Mar 2 '18 at 14:52










1 Answer
1






active

oldest

votes


















0














I have managed to create a test case that at least for MySQL 5.6 demonstrates, for all intents and purposes, that the behaviour is undefined. Consider these 3 examples creating a "diamond"-shape between A, B, C and D.



Example 1



CREATE TABLE `a` (id INT UNSIGNED NOT NULL,
PRIMARY KEY (id)
) ENGINE = INNODB;

CREATE TABLE `b` (
id INT UNSIGNED NOT NULL,
a INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a) REFERENCES a (id) ON DELETE CASCADE
) ENGINE = INNODB;

CREATE TABLE `c` (
id INT UNSIGNED NOT NULL,
a INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a) REFERENCES a (id) ON DELETE CASCADE
) ENGINE = INNODB;

CREATE TABLE `d` (
id INT UNSIGNED NOT NULL,
b INT UNSIGNED NOT NULL,
c INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (id) REFERENCES b (id) ON DELETE CASCADE,
FOREIGN KEY (id) REFERENCES c (id) ON DELETE CASCADE
) ENGINE = INNODB;

INSERT INTO a VALUES (1);
INSERT INTO b VALUES (1, 1);
INSERT INTO c VALUES (1, 1);
INSERT INTO d VALUES (1, 1, 1);

DELETE FROM a;


Delete from a is successful as expected, as all keys are CASCADE.



Example 2



CREATE TABLE `a` (
id INT UNSIGNED NOT NULL,
PRIMARY KEY (id)
) ENGINE = INNODB;

CREATE TABLE `b` (
id INT UNSIGNED NOT NULL,
a INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a) REFERENCES a (id) ON DELETE CASCADE
) ENGINE = INNODB;

CREATE TABLE `c` (
id INT UNSIGNED NOT NULL,
a INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a) REFERENCES a (id) ON DELETE CASCADE
) ENGINE = INNODB;

CREATE TABLE `d` (
id INT UNSIGNED NOT NULL,
b INT UNSIGNED NOT NULL,
c INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (id) REFERENCES b (id) ON DELETE CASCADE,
FOREIGN KEY (id) REFERENCES c (id) ON DELETE RESTRICT
) ENGINE = INNODB;

INSERT INTO a VALUES (1);
INSERT INTO b VALUES (1, 1);
INSERT INTO c VALUES (1, 1);
INSERT INTO d VALUES (1, 1, 1);

DELETE FROM a;


Notice that d now has a RESTRICT to c. I would consider this case ambiguous as it forces you to consider which foreign key "wins". CASCADE or RESTICT, what is picked?



The result is that all rows are deleted.



Example 3



CREATE TABLE `a` (
id INT UNSIGNED NOT NULL,
PRIMARY KEY (id)
) ENGINE = INNODB;

CREATE TABLE `b` (
id INT UNSIGNED NOT NULL,
a INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a) REFERENCES a (id) ON DELETE CASCADE
) ENGINE = INNODB;

CREATE TABLE `c` (
id INT UNSIGNED NOT NULL,
a INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a) REFERENCES a (id) ON DELETE CASCADE
) ENGINE = INNODB;

CREATE TABLE `d` (
id INT UNSIGNED NOT NULL,
b INT UNSIGNED NOT NULL,
c INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (id) REFERENCES b (id) ON DELETE RESTRICT,
FOREIGN KEY (id) REFERENCES c (id) ON DELETE CASCADE
) ENGINE = INNODB;

INSERT INTO a VALUES (1);
INSERT INTO b VALUES (1, 1);
INSERT INTO c VALUES (1, 1);
INSERT INTO d VALUES (1, 1, 1);

DELETE FROM a;


Notice that the only difference is the change of what foreign key is RESTRICT from d. This example however, fails with




Error Code: 1451
Cannot delete or update a parent row: a foreign key constraint fails (hello.d, CONSTRAINT d_ibfk_1 FOREIGN KEY (id) REFERENCES b (id))




While logically, it's the same as Example 2. Without having looked at the source code of MySQL, I strongly suspect that the foreign keys are "applied" in lexical order based on their name. This is also the order the foreign keys are listed by mysqldump.



Without knowing whether what I'm testing here has a defined behaviour or not based on a higher logic, it's hard to know if this demonstrates either a bug, or simply the behaviour in MySQL.



Regardless, as it stands, this example shows that in practical terms I'd say that for all intents and purposes, when having mixed CASCADE and RESTRICT, the behaviour is undefined as it's not in any way sound that you should depend on the names given to foreign keys.






share|improve this answer
























  • Another possible explaination is that deletion is performed by something similar to a depth-first traversal that fails whenever a RESTRICT is encountered. Traversal itself could possibly make use of a lexical order. Would need to look at source code. Still, as close to undefined as it gets in my opinion.

    – Matthias
    Mar 5 '18 at 10:11












Your Answer








StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "182"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f199171%2ftables-with-mixed-on-delete-cascade-and-on-delete-restrict-rule-set-with-recurs%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









0














I have managed to create a test case that at least for MySQL 5.6 demonstrates, for all intents and purposes, that the behaviour is undefined. Consider these 3 examples creating a "diamond"-shape between A, B, C and D.



Example 1



CREATE TABLE `a` (id INT UNSIGNED NOT NULL,
PRIMARY KEY (id)
) ENGINE = INNODB;

CREATE TABLE `b` (
id INT UNSIGNED NOT NULL,
a INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a) REFERENCES a (id) ON DELETE CASCADE
) ENGINE = INNODB;

CREATE TABLE `c` (
id INT UNSIGNED NOT NULL,
a INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a) REFERENCES a (id) ON DELETE CASCADE
) ENGINE = INNODB;

CREATE TABLE `d` (
id INT UNSIGNED NOT NULL,
b INT UNSIGNED NOT NULL,
c INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (id) REFERENCES b (id) ON DELETE CASCADE,
FOREIGN KEY (id) REFERENCES c (id) ON DELETE CASCADE
) ENGINE = INNODB;

INSERT INTO a VALUES (1);
INSERT INTO b VALUES (1, 1);
INSERT INTO c VALUES (1, 1);
INSERT INTO d VALUES (1, 1, 1);

DELETE FROM a;


Delete from a is successful as expected, as all keys are CASCADE.



Example 2



CREATE TABLE `a` (
id INT UNSIGNED NOT NULL,
PRIMARY KEY (id)
) ENGINE = INNODB;

CREATE TABLE `b` (
id INT UNSIGNED NOT NULL,
a INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a) REFERENCES a (id) ON DELETE CASCADE
) ENGINE = INNODB;

CREATE TABLE `c` (
id INT UNSIGNED NOT NULL,
a INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a) REFERENCES a (id) ON DELETE CASCADE
) ENGINE = INNODB;

CREATE TABLE `d` (
id INT UNSIGNED NOT NULL,
b INT UNSIGNED NOT NULL,
c INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (id) REFERENCES b (id) ON DELETE CASCADE,
FOREIGN KEY (id) REFERENCES c (id) ON DELETE RESTRICT
) ENGINE = INNODB;

INSERT INTO a VALUES (1);
INSERT INTO b VALUES (1, 1);
INSERT INTO c VALUES (1, 1);
INSERT INTO d VALUES (1, 1, 1);

DELETE FROM a;


Notice that d now has a RESTRICT to c. I would consider this case ambiguous as it forces you to consider which foreign key "wins". CASCADE or RESTICT, what is picked?



The result is that all rows are deleted.



Example 3



CREATE TABLE `a` (
id INT UNSIGNED NOT NULL,
PRIMARY KEY (id)
) ENGINE = INNODB;

CREATE TABLE `b` (
id INT UNSIGNED NOT NULL,
a INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a) REFERENCES a (id) ON DELETE CASCADE
) ENGINE = INNODB;

CREATE TABLE `c` (
id INT UNSIGNED NOT NULL,
a INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a) REFERENCES a (id) ON DELETE CASCADE
) ENGINE = INNODB;

CREATE TABLE `d` (
id INT UNSIGNED NOT NULL,
b INT UNSIGNED NOT NULL,
c INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (id) REFERENCES b (id) ON DELETE RESTRICT,
FOREIGN KEY (id) REFERENCES c (id) ON DELETE CASCADE
) ENGINE = INNODB;

INSERT INTO a VALUES (1);
INSERT INTO b VALUES (1, 1);
INSERT INTO c VALUES (1, 1);
INSERT INTO d VALUES (1, 1, 1);

DELETE FROM a;


Notice that the only difference is the change of what foreign key is RESTRICT from d. This example however, fails with




Error Code: 1451
Cannot delete or update a parent row: a foreign key constraint fails (hello.d, CONSTRAINT d_ibfk_1 FOREIGN KEY (id) REFERENCES b (id))




While logically, it's the same as Example 2. Without having looked at the source code of MySQL, I strongly suspect that the foreign keys are "applied" in lexical order based on their name. This is also the order the foreign keys are listed by mysqldump.



Without knowing whether what I'm testing here has a defined behaviour or not based on a higher logic, it's hard to know if this demonstrates either a bug, or simply the behaviour in MySQL.



Regardless, as it stands, this example shows that in practical terms I'd say that for all intents and purposes, when having mixed CASCADE and RESTRICT, the behaviour is undefined as it's not in any way sound that you should depend on the names given to foreign keys.






share|improve this answer
























  • Another possible explaination is that deletion is performed by something similar to a depth-first traversal that fails whenever a RESTRICT is encountered. Traversal itself could possibly make use of a lexical order. Would need to look at source code. Still, as close to undefined as it gets in my opinion.

    – Matthias
    Mar 5 '18 at 10:11
















0














I have managed to create a test case that at least for MySQL 5.6 demonstrates, for all intents and purposes, that the behaviour is undefined. Consider these 3 examples creating a "diamond"-shape between A, B, C and D.



Example 1



CREATE TABLE `a` (id INT UNSIGNED NOT NULL,
PRIMARY KEY (id)
) ENGINE = INNODB;

CREATE TABLE `b` (
id INT UNSIGNED NOT NULL,
a INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a) REFERENCES a (id) ON DELETE CASCADE
) ENGINE = INNODB;

CREATE TABLE `c` (
id INT UNSIGNED NOT NULL,
a INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a) REFERENCES a (id) ON DELETE CASCADE
) ENGINE = INNODB;

CREATE TABLE `d` (
id INT UNSIGNED NOT NULL,
b INT UNSIGNED NOT NULL,
c INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (id) REFERENCES b (id) ON DELETE CASCADE,
FOREIGN KEY (id) REFERENCES c (id) ON DELETE CASCADE
) ENGINE = INNODB;

INSERT INTO a VALUES (1);
INSERT INTO b VALUES (1, 1);
INSERT INTO c VALUES (1, 1);
INSERT INTO d VALUES (1, 1, 1);

DELETE FROM a;


Delete from a is successful as expected, as all keys are CASCADE.



Example 2



CREATE TABLE `a` (
id INT UNSIGNED NOT NULL,
PRIMARY KEY (id)
) ENGINE = INNODB;

CREATE TABLE `b` (
id INT UNSIGNED NOT NULL,
a INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a) REFERENCES a (id) ON DELETE CASCADE
) ENGINE = INNODB;

CREATE TABLE `c` (
id INT UNSIGNED NOT NULL,
a INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a) REFERENCES a (id) ON DELETE CASCADE
) ENGINE = INNODB;

CREATE TABLE `d` (
id INT UNSIGNED NOT NULL,
b INT UNSIGNED NOT NULL,
c INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (id) REFERENCES b (id) ON DELETE CASCADE,
FOREIGN KEY (id) REFERENCES c (id) ON DELETE RESTRICT
) ENGINE = INNODB;

INSERT INTO a VALUES (1);
INSERT INTO b VALUES (1, 1);
INSERT INTO c VALUES (1, 1);
INSERT INTO d VALUES (1, 1, 1);

DELETE FROM a;


Notice that d now has a RESTRICT to c. I would consider this case ambiguous as it forces you to consider which foreign key "wins". CASCADE or RESTICT, what is picked?



The result is that all rows are deleted.



Example 3



CREATE TABLE `a` (
id INT UNSIGNED NOT NULL,
PRIMARY KEY (id)
) ENGINE = INNODB;

CREATE TABLE `b` (
id INT UNSIGNED NOT NULL,
a INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a) REFERENCES a (id) ON DELETE CASCADE
) ENGINE = INNODB;

CREATE TABLE `c` (
id INT UNSIGNED NOT NULL,
a INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a) REFERENCES a (id) ON DELETE CASCADE
) ENGINE = INNODB;

CREATE TABLE `d` (
id INT UNSIGNED NOT NULL,
b INT UNSIGNED NOT NULL,
c INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (id) REFERENCES b (id) ON DELETE RESTRICT,
FOREIGN KEY (id) REFERENCES c (id) ON DELETE CASCADE
) ENGINE = INNODB;

INSERT INTO a VALUES (1);
INSERT INTO b VALUES (1, 1);
INSERT INTO c VALUES (1, 1);
INSERT INTO d VALUES (1, 1, 1);

DELETE FROM a;


Notice that the only difference is the change of what foreign key is RESTRICT from d. This example however, fails with




Error Code: 1451
Cannot delete or update a parent row: a foreign key constraint fails (hello.d, CONSTRAINT d_ibfk_1 FOREIGN KEY (id) REFERENCES b (id))




While logically, it's the same as Example 2. Without having looked at the source code of MySQL, I strongly suspect that the foreign keys are "applied" in lexical order based on their name. This is also the order the foreign keys are listed by mysqldump.



Without knowing whether what I'm testing here has a defined behaviour or not based on a higher logic, it's hard to know if this demonstrates either a bug, or simply the behaviour in MySQL.



Regardless, as it stands, this example shows that in practical terms I'd say that for all intents and purposes, when having mixed CASCADE and RESTRICT, the behaviour is undefined as it's not in any way sound that you should depend on the names given to foreign keys.






share|improve this answer
























  • Another possible explaination is that deletion is performed by something similar to a depth-first traversal that fails whenever a RESTRICT is encountered. Traversal itself could possibly make use of a lexical order. Would need to look at source code. Still, as close to undefined as it gets in my opinion.

    – Matthias
    Mar 5 '18 at 10:11














0












0








0







I have managed to create a test case that at least for MySQL 5.6 demonstrates, for all intents and purposes, that the behaviour is undefined. Consider these 3 examples creating a "diamond"-shape between A, B, C and D.



Example 1



CREATE TABLE `a` (id INT UNSIGNED NOT NULL,
PRIMARY KEY (id)
) ENGINE = INNODB;

CREATE TABLE `b` (
id INT UNSIGNED NOT NULL,
a INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a) REFERENCES a (id) ON DELETE CASCADE
) ENGINE = INNODB;

CREATE TABLE `c` (
id INT UNSIGNED NOT NULL,
a INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a) REFERENCES a (id) ON DELETE CASCADE
) ENGINE = INNODB;

CREATE TABLE `d` (
id INT UNSIGNED NOT NULL,
b INT UNSIGNED NOT NULL,
c INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (id) REFERENCES b (id) ON DELETE CASCADE,
FOREIGN KEY (id) REFERENCES c (id) ON DELETE CASCADE
) ENGINE = INNODB;

INSERT INTO a VALUES (1);
INSERT INTO b VALUES (1, 1);
INSERT INTO c VALUES (1, 1);
INSERT INTO d VALUES (1, 1, 1);

DELETE FROM a;


Delete from a is successful as expected, as all keys are CASCADE.



Example 2



CREATE TABLE `a` (
id INT UNSIGNED NOT NULL,
PRIMARY KEY (id)
) ENGINE = INNODB;

CREATE TABLE `b` (
id INT UNSIGNED NOT NULL,
a INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a) REFERENCES a (id) ON DELETE CASCADE
) ENGINE = INNODB;

CREATE TABLE `c` (
id INT UNSIGNED NOT NULL,
a INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a) REFERENCES a (id) ON DELETE CASCADE
) ENGINE = INNODB;

CREATE TABLE `d` (
id INT UNSIGNED NOT NULL,
b INT UNSIGNED NOT NULL,
c INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (id) REFERENCES b (id) ON DELETE CASCADE,
FOREIGN KEY (id) REFERENCES c (id) ON DELETE RESTRICT
) ENGINE = INNODB;

INSERT INTO a VALUES (1);
INSERT INTO b VALUES (1, 1);
INSERT INTO c VALUES (1, 1);
INSERT INTO d VALUES (1, 1, 1);

DELETE FROM a;


Notice that d now has a RESTRICT to c. I would consider this case ambiguous as it forces you to consider which foreign key "wins". CASCADE or RESTICT, what is picked?



The result is that all rows are deleted.



Example 3



CREATE TABLE `a` (
id INT UNSIGNED NOT NULL,
PRIMARY KEY (id)
) ENGINE = INNODB;

CREATE TABLE `b` (
id INT UNSIGNED NOT NULL,
a INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a) REFERENCES a (id) ON DELETE CASCADE
) ENGINE = INNODB;

CREATE TABLE `c` (
id INT UNSIGNED NOT NULL,
a INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a) REFERENCES a (id) ON DELETE CASCADE
) ENGINE = INNODB;

CREATE TABLE `d` (
id INT UNSIGNED NOT NULL,
b INT UNSIGNED NOT NULL,
c INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (id) REFERENCES b (id) ON DELETE RESTRICT,
FOREIGN KEY (id) REFERENCES c (id) ON DELETE CASCADE
) ENGINE = INNODB;

INSERT INTO a VALUES (1);
INSERT INTO b VALUES (1, 1);
INSERT INTO c VALUES (1, 1);
INSERT INTO d VALUES (1, 1, 1);

DELETE FROM a;


Notice that the only difference is the change of what foreign key is RESTRICT from d. This example however, fails with




Error Code: 1451
Cannot delete or update a parent row: a foreign key constraint fails (hello.d, CONSTRAINT d_ibfk_1 FOREIGN KEY (id) REFERENCES b (id))




While logically, it's the same as Example 2. Without having looked at the source code of MySQL, I strongly suspect that the foreign keys are "applied" in lexical order based on their name. This is also the order the foreign keys are listed by mysqldump.



Without knowing whether what I'm testing here has a defined behaviour or not based on a higher logic, it's hard to know if this demonstrates either a bug, or simply the behaviour in MySQL.



Regardless, as it stands, this example shows that in practical terms I'd say that for all intents and purposes, when having mixed CASCADE and RESTRICT, the behaviour is undefined as it's not in any way sound that you should depend on the names given to foreign keys.






share|improve this answer













I have managed to create a test case that at least for MySQL 5.6 demonstrates, for all intents and purposes, that the behaviour is undefined. Consider these 3 examples creating a "diamond"-shape between A, B, C and D.



Example 1



CREATE TABLE `a` (id INT UNSIGNED NOT NULL,
PRIMARY KEY (id)
) ENGINE = INNODB;

CREATE TABLE `b` (
id INT UNSIGNED NOT NULL,
a INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a) REFERENCES a (id) ON DELETE CASCADE
) ENGINE = INNODB;

CREATE TABLE `c` (
id INT UNSIGNED NOT NULL,
a INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a) REFERENCES a (id) ON DELETE CASCADE
) ENGINE = INNODB;

CREATE TABLE `d` (
id INT UNSIGNED NOT NULL,
b INT UNSIGNED NOT NULL,
c INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (id) REFERENCES b (id) ON DELETE CASCADE,
FOREIGN KEY (id) REFERENCES c (id) ON DELETE CASCADE
) ENGINE = INNODB;

INSERT INTO a VALUES (1);
INSERT INTO b VALUES (1, 1);
INSERT INTO c VALUES (1, 1);
INSERT INTO d VALUES (1, 1, 1);

DELETE FROM a;


Delete from a is successful as expected, as all keys are CASCADE.



Example 2



CREATE TABLE `a` (
id INT UNSIGNED NOT NULL,
PRIMARY KEY (id)
) ENGINE = INNODB;

CREATE TABLE `b` (
id INT UNSIGNED NOT NULL,
a INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a) REFERENCES a (id) ON DELETE CASCADE
) ENGINE = INNODB;

CREATE TABLE `c` (
id INT UNSIGNED NOT NULL,
a INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a) REFERENCES a (id) ON DELETE CASCADE
) ENGINE = INNODB;

CREATE TABLE `d` (
id INT UNSIGNED NOT NULL,
b INT UNSIGNED NOT NULL,
c INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (id) REFERENCES b (id) ON DELETE CASCADE,
FOREIGN KEY (id) REFERENCES c (id) ON DELETE RESTRICT
) ENGINE = INNODB;

INSERT INTO a VALUES (1);
INSERT INTO b VALUES (1, 1);
INSERT INTO c VALUES (1, 1);
INSERT INTO d VALUES (1, 1, 1);

DELETE FROM a;


Notice that d now has a RESTRICT to c. I would consider this case ambiguous as it forces you to consider which foreign key "wins". CASCADE or RESTICT, what is picked?



The result is that all rows are deleted.



Example 3



CREATE TABLE `a` (
id INT UNSIGNED NOT NULL,
PRIMARY KEY (id)
) ENGINE = INNODB;

CREATE TABLE `b` (
id INT UNSIGNED NOT NULL,
a INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a) REFERENCES a (id) ON DELETE CASCADE
) ENGINE = INNODB;

CREATE TABLE `c` (
id INT UNSIGNED NOT NULL,
a INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a) REFERENCES a (id) ON DELETE CASCADE
) ENGINE = INNODB;

CREATE TABLE `d` (
id INT UNSIGNED NOT NULL,
b INT UNSIGNED NOT NULL,
c INT UNSIGNED NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (id) REFERENCES b (id) ON DELETE RESTRICT,
FOREIGN KEY (id) REFERENCES c (id) ON DELETE CASCADE
) ENGINE = INNODB;

INSERT INTO a VALUES (1);
INSERT INTO b VALUES (1, 1);
INSERT INTO c VALUES (1, 1);
INSERT INTO d VALUES (1, 1, 1);

DELETE FROM a;


Notice that the only difference is the change of what foreign key is RESTRICT from d. This example however, fails with




Error Code: 1451
Cannot delete or update a parent row: a foreign key constraint fails (hello.d, CONSTRAINT d_ibfk_1 FOREIGN KEY (id) REFERENCES b (id))




While logically, it's the same as Example 2. Without having looked at the source code of MySQL, I strongly suspect that the foreign keys are "applied" in lexical order based on their name. This is also the order the foreign keys are listed by mysqldump.



Without knowing whether what I'm testing here has a defined behaviour or not based on a higher logic, it's hard to know if this demonstrates either a bug, or simply the behaviour in MySQL.



Regardless, as it stands, this example shows that in practical terms I'd say that for all intents and purposes, when having mixed CASCADE and RESTRICT, the behaviour is undefined as it's not in any way sound that you should depend on the names given to foreign keys.







share|improve this answer












share|improve this answer



share|improve this answer










answered Mar 5 '18 at 10:06









MatthiasMatthias

61




61













  • Another possible explaination is that deletion is performed by something similar to a depth-first traversal that fails whenever a RESTRICT is encountered. Traversal itself could possibly make use of a lexical order. Would need to look at source code. Still, as close to undefined as it gets in my opinion.

    – Matthias
    Mar 5 '18 at 10:11



















  • Another possible explaination is that deletion is performed by something similar to a depth-first traversal that fails whenever a RESTRICT is encountered. Traversal itself could possibly make use of a lexical order. Would need to look at source code. Still, as close to undefined as it gets in my opinion.

    – Matthias
    Mar 5 '18 at 10:11

















Another possible explaination is that deletion is performed by something similar to a depth-first traversal that fails whenever a RESTRICT is encountered. Traversal itself could possibly make use of a lexical order. Would need to look at source code. Still, as close to undefined as it gets in my opinion.

– Matthias
Mar 5 '18 at 10:11





Another possible explaination is that deletion is performed by something similar to a depth-first traversal that fails whenever a RESTRICT is encountered. Traversal itself could possibly make use of a lexical order. Would need to look at source code. Still, as close to undefined as it gets in my opinion.

– Matthias
Mar 5 '18 at 10:11


















draft saved

draft discarded




















































Thanks for contributing an answer to Database Administrators Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f199171%2ftables-with-mixed-on-delete-cascade-and-on-delete-restrict-rule-set-with-recurs%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

ORA-01691 (unable to extend lob segment) even though my tablespace has AUTOEXTEND onORA-01692: unable to...

Always On Availability groups resolving state after failover - Remote harden of transaction...

Circunscripción electoral de Guipúzcoa Referencias Menú de navegaciónLas claves del sistema electoral en...