[英]Inner join on delete query is that bad?
我目前正在嘗試使用C#從MySQL表中刪除一行。
我有兩個非常基本的表:“ head_doc”和“ Doc_details”。 Head_doc包含一個名為id_doc的字段。 Doc_details還有一個名為id_doc的字段以及其他各種字段。
我試圖刪除在head_doc中可以找到的特定id_doc的Doc_details中的所有詳細信息。
這是我的查詢,但有人告訴我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
)
但是,如果您想擺脫兩個表中都有特定ID的所有記錄,為了清楚起見,建議您刪除delete語句是一個好主意:
delete from doc_details where id_doc = <value>
delete from doc_head where id_doc = <value>
注意:如果您在子表上設置了外鍵約束,並且想要從父表中刪除記錄,那么數據庫引擎將阻止您在沒有子記錄的情況下將記錄從父表中刪除。首先刪除。 盡可能設置外鍵約束是一個好主意,以確保刪除父記錄時子表中沒有孤立記錄。
不,在DELETE
語句中使用聯接操作不是壞習慣。 這是一種常見的模式。
我不確定誰告訴您這是“不良編程”,如果他們有任何理由告訴您。
對於從一個以上的表中刪除行,MySQL可能以導致違反外鍵約束的順序執行操作(對於InnoDB表)。
例如,MySQL可能試圖從刪除一行head_doc
它刪除相關的子行之前 doc_details
。
如果您使用涉及具有外鍵約束的InnoDB表的多表
DELETE
語句,則MySQL優化器可能以與其父/子關系不同的順序處理表。 在這種情況下,該語句將失敗並回滾。 相反,您應該從單個表中刪除,並依靠InnoDB提供的ON DELETE
功能來相應地修改其他表。
參考: http : //dev.mysql.com/doc/refman/5.5/en/delete.html
或者,有時我們可以通過使用單獨的語句從每個表中刪除來解決該問題。
我們注意到,由於內部doc_details
,問題中的查詢將僅從head_doc
中刪除在head_doc
中具有相關子行的行。 如果沒有任何子行, head_doc
在head_doc
中head_doc
行。 那不一定是不好的編程。 但這有點奇怪。
假設您要從兩個表中刪除行,則可能需要外部 head_doc
,因此即使head_doc
不存在匹配的子行, doc_detais
從head_doc
刪除行
DELETE d.*
, h.*
FROM head_doc h
LEFT
JOIN doc_details d
ON d.id_doc = h.id_doc
WHERE h.id_doc = ?
假設您在兩個表中都有id_doc
,那么一個更簡單的模式是使用兩個單獨的DELETE語句,首先從子表中刪除,然后從父表中刪除:
DELETE FROM doc_details WHERE id_doc = ?
DELETE FROM head_doc WHERE id_doc = ?
如果要從head_doc
中刪除的行是由除id_doc
列之外的其他條件標識的,則在doc_details
中不可用的doc_details
,我們可以使用JOIN操作來標識子表中應刪除的行
例如,首先,從子表中刪除行(使用JOIN操作)
DELETE d.*
FROM head_doc h
JOIN doc_details d
ON d.id_doc = h.id_doc
WHERE h.somecol < ?
AND h.othercol = ?
然后,從父表中刪除:
DELETE h.*
FROM head_doc h
WHERE h.somecol < ?
AND h.othercol = ?
總之,在DELETE中使用JOIN操作不一定是“不良編程”。 我們需要注意一些警告。 有時,使用聯接操作是最好的方法。 這實際上取決於您要實現的目標。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.