No, it's not bad practice to use a join operation in a DELETE
statement. It's a common pattern.
I'm not sure whose told you that it was "bad programming", if they have any rationale for telling you that.
For delete rows from more than one table, there is a possibility that MySQL may perform the operations in an order which causes foreign key constraints to be violated (with InnoDB tables).
For example, MySQL may attempt to delete a row from head_doc
before it deletes the related child rows from doc_details
.
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.
Reference: http://dev.mysql.com/doc/refman/5.5/en/delete.html
Or, we can sometimes workaround that issue by using separate statements to delete from each table.
We note that the query in the question will only only remove rows from head_doc
that have a related child row in doc_details
, because of the inner join operation. That will leave row(s) in head_doc
if there aren't any child rows. That's not necessarily bad programming. But it is a bit odd.
Given that you want to remove rows from the two tables, you probably want an outer join, so you delete rows from head_doc
even when no matching child rows exist in doc_detais
DELETE d.*
, h.*
FROM head_doc h
LEFT
JOIN doc_details d
ON d.id_doc = h.id_doc
WHERE h.id_doc = ?
Given that you have id_doc
in both tables, a simpler pattern would be to use two separate DELETE statements, first delete from the child table, then the parent:
DELETE FROM doc_details WHERE id_doc = ?
DELETE FROM head_doc WHERE id_doc = ?
In cases where the rows to be removed from head_doc
are identified by some other condition than on the id_doc
column, on columns that are not available in doc_details
, we can use a JOIN operation to identify the rows in the child table that should be removed
e.g. first, delete rows from the child table (using a JOIN operation)
DELETE d.*
FROM head_doc h
JOIN doc_details d
ON d.id_doc = h.id_doc
WHERE h.somecol < ?
AND h.othercol = ?
Then, delete from the parent table:
DELETE h.*
FROM head_doc h
WHERE h.somecol < ?
AND h.othercol = ?
In summary, using a JOIN operation in a DELETE is not necessarily "bad programming". There are some caveats we need to be aware of. Sometimes, using a join operation is the best approach. It really depends on what you want to achieve.