删除查询中的内部连接有那么糟糕吗?
Inner join on delete query is that bad?
我目前正在尝试使用 C# 从 MySQL table 中删除一行。
我有两个非常基本的 table:'head_doc' 和 'Doc_details'。 Head_doc 包含一个名为 id_doc 的字段。 Doc_details 还有一个名为 id_doc 的字段和其他各种字段。
我正在尝试删除 Doc_details 中某个特定 id_doc 中的所有详细信息,该 id_doc 可以在 head_doc.
中找到
这是我的查询,但我被告知在 DELETE 查询上使用 INNER JOIN 是糟糕的编程。我该如何更改它?
DELETE h.*,d.*
FROM head_doc h
INNER JOIN
doc_details d
ON h.id_doc = d.id_doc
WHERE h.id_doc= id_doc;
如果您只是想删除 doc_details 中没有相应父记录的记录(又名孤立记录),那么就这样做(这可以通过添加外键约束来避免. 请参阅下面的注释):
delete
from doc_details
where id_doc not in (
select id_doc from head_doc
)
但是,如果您想删除两个 table 中具有特定 id 的所有记录,为了清楚起见,拆分删除语句可能是个好主意:
delete from doc_details where id_doc = <value>
delete from doc_head where id_doc = <value>
注意: 如果您在子 table 上设置了外键约束,并且您想要从父 table 中删除一条记录,如果未先删除子记录,数据库引擎将阻止您从父 table 中删除记录。只要有可能,设置外键约束是一个好主意,以确保在删除父记录时子 table 中没有孤立记录。
不,在 DELETE
语句中使用连接操作不是坏习惯。这是一个常见的模式。
我不确定是谁告诉你那是 "bad programming",他们是否有任何理由告诉你。
对于从多个 table 中删除行,MySQL 可能会按照导致违反外键约束的顺序执行操作(使用 InnoDB tables).
例如,MySQL 可能会尝试从 head_doc
中删除一行,然后 它会从 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.
参考:http://dev.mysql.com/doc/refman/5.5/en/delete.html
或者,有时我们可以通过使用 separate 语句从每个 table.
中删除来解决该问题
我们注意到问题中的查询只会从 head_doc
中删除在 doc_details
中具有相关子行的行,因为内部连接操作。如果没有任何子行,那将在 head_doc
中留下行。这不一定是糟糕的编程。但是有点奇怪。
鉴于您要从两个 table 中删除行,您可能需要一个 outer 连接,因此您甚至从 head_doc
中删除行当 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 = ?
鉴于您在两个 table 中都有 id_doc
,一个更简单的模式是使用两个单独的 DELETE 语句,首先从子 table 中删除,然后从父中删除:
DELETE FROM doc_details WHERE id_doc = ?
DELETE FROM head_doc WHERE id_doc = ?
如果要从 head_doc
中删除的行是由 id_doc
列以外的某些其他条件标识的,则 不是 的列在 doc_details
中可用,我们可以使用 JOIN 操作来识别子 table 中应该删除的行
例如首先,从子 table 中删除行(使用 JOIN 操作)
DELETE d.*
FROM head_doc h
JOIN doc_details d
ON d.id_doc = h.id_doc
WHERE h.somecol < ?
AND h.othercol = ?
然后,从父级删除table:
DELETE h.*
FROM head_doc h
WHERE h.somecol < ?
AND h.othercol = ?
综上所述,在DELETE中使用JOIN操作不一定"bad programming"。我们需要注意一些注意事项。有时,使用连接操作是最好的方法。这实际上取决于您想要实现的目标。
我目前正在尝试使用 C# 从 MySQL table 中删除一行。
我有两个非常基本的 table:'head_doc' 和 'Doc_details'。 Head_doc 包含一个名为 id_doc 的字段。 Doc_details 还有一个名为 id_doc 的字段和其他各种字段。
我正在尝试删除 Doc_details 中某个特定 id_doc 中的所有详细信息,该 id_doc 可以在 head_doc.
中找到
这是我的查询,但我被告知在 DELETE 查询上使用 INNER JOIN 是糟糕的编程。我该如何更改它?
DELETE h.*,d.*
FROM head_doc h
INNER JOIN
doc_details d
ON h.id_doc = d.id_doc
WHERE h.id_doc= id_doc;
如果您只是想删除 doc_details 中没有相应父记录的记录(又名孤立记录),那么就这样做(这可以通过添加外键约束来避免. 请参阅下面的注释):
delete
from doc_details
where id_doc not in (
select id_doc from head_doc
)
但是,如果您想删除两个 table 中具有特定 id 的所有记录,为了清楚起见,拆分删除语句可能是个好主意:
delete from doc_details where id_doc = <value>
delete from doc_head where id_doc = <value>
注意: 如果您在子 table 上设置了外键约束,并且您想要从父 table 中删除一条记录,如果未先删除子记录,数据库引擎将阻止您从父 table 中删除记录。只要有可能,设置外键约束是一个好主意,以确保在删除父记录时子 table 中没有孤立记录。
不,在 DELETE
语句中使用连接操作不是坏习惯。这是一个常见的模式。
我不确定是谁告诉你那是 "bad programming",他们是否有任何理由告诉你。
对于从多个 table 中删除行,MySQL 可能会按照导致违反外键约束的顺序执行操作(使用 InnoDB tables).
例如,MySQL 可能会尝试从 head_doc
中删除一行,然后 它会从 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 theON DELETE
capabilities that InnoDB provides to cause the other tables to be modified accordingly.
参考:http://dev.mysql.com/doc/refman/5.5/en/delete.html
或者,有时我们可以通过使用 separate 语句从每个 table.
中删除来解决该问题我们注意到问题中的查询只会从 head_doc
中删除在 doc_details
中具有相关子行的行,因为内部连接操作。如果没有任何子行,那将在 head_doc
中留下行。这不一定是糟糕的编程。但是有点奇怪。
鉴于您要从两个 table 中删除行,您可能需要一个 outer 连接,因此您甚至从 head_doc
中删除行当 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 = ?
鉴于您在两个 table 中都有 id_doc
,一个更简单的模式是使用两个单独的 DELETE 语句,首先从子 table 中删除,然后从父中删除:
DELETE FROM doc_details WHERE id_doc = ?
DELETE FROM head_doc WHERE id_doc = ?
如果要从 head_doc
中删除的行是由 id_doc
列以外的某些其他条件标识的,则 不是 的列在 doc_details
中可用,我们可以使用 JOIN 操作来识别子 table 中应该删除的行
例如首先,从子 table 中删除行(使用 JOIN 操作)
DELETE d.*
FROM head_doc h
JOIN doc_details d
ON d.id_doc = h.id_doc
WHERE h.somecol < ?
AND h.othercol = ?
然后,从父级删除table:
DELETE h.*
FROM head_doc h
WHERE h.somecol < ?
AND h.othercol = ?
综上所述,在DELETE中使用JOIN操作不一定"bad programming"。我们需要注意一些注意事项。有时,使用连接操作是最好的方法。这实际上取决于您想要实现的目标。