Skip to content
Advertisement

Inconsistent delete query with left join of multiple tables

I have three tables in MySQL v5.6 created by:

CREATE TABLE tm (
    id INT AUTO_INCREMENT,
    PRIMARY KEY (id)
);
CREATE TABLE th (
    id INT AUTO_INCREMENT,
    PRIMARY KEY (id)
);
CREATE TABLE tr (
    id INT AUTO_INCREMENT,
    tm_id INT,
    th_id INT,
    PRIMARY KEY (id), 
    CONSTRAINT fk_1 FOREIGN KEY (tm_id) REFERENCES tm (id) ON DELETE CASCADE ON UPDATE CASCADE,
    CONSTRAINT fk_2 FOREIGN KEY (th_id) REFERENCES th (id) ON DELETE CASCADE ON UPDATE CASCADE
);


INSERT INTO tm (id) VALUES (101);
INSERT INTO tm (id) VALUES (102);
INSERT INTO th (id) VALUES (1);
INSERT INTO tr (tm_id, th_id) VALUES (101,1), (102,1);

So in the end I have three tables with following data:

th

| id |
|----|
|  1 |


tr

| id  | tm_id   | th_id |
|-----|---------|-------|
|  11 |     101 |     1 |
|  12 |     102 |     1 |


tm 

| id   |
|------|
|  101 |
|  102 |

And what I am trying to do is to delete all of them with one SQL query:

DELETE th, tr, tm
FROM th
LEFT JOIN tr ON tr.th_id = th.id
LEFT JOIN tm ON tr.tm_id = tm.id
WHERE th.id = 1;

As a result th and tr tables will be blank but tm will be left with id=102

+------+
|   id |
+------+
|  102 |
+------+

And I am not searching for better query but trying to understand why tm.id=101 was deleted but tm.id=102 was left in the table?

Advertisement

Answer

This is the result of the InnoDB storage engine which is used (as default) to create the tables and the foreign key constraints.

Check the demo without foreign keys and the result is that all rows of all tables are deleted.

You would get the same result, even with the foreign key constraints if you created the tables with the MyISAM storage engine.
Check the demo.

But for the InnoDB storage engine and the foreign key constraints, as it is mentioned in 13.2.2 DELETE Statement:

If you use a multiple-table DELETE statement involving InnoDB tables for which there are foreign key constraints, the MySQL optimizer might process tables in an order that differs from that of their parent/child relationship. In this case, the statement fails and rolls back. Instead, you should delete from a single table and rely on the ON DELETE capabilities that InnoDB provides to cause the other tables to be modified accordingly.

so what you get may be the result of a rollback for the deletion of id = 102 of tm, because the order of the tables processed is such that it would violate a foreign key constraint.
Check the demo.

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement