删除查询的内连接是不是很糟糕?

时间:2015-05-25 16:22:12

标签: c# mysql inner-join sql-delete

我目前正在尝试使用C#从MySQL表中删除一行 我有两个非常基本的表:'head_doc'和'Doc_details'。 Head_doc包含一个名为id_doc的字段。 Doc_details还有一个名为id_doc的字段和其他各种字段 我正在尝试删除doc_details中可以在head_doc中找到的特定id_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;

2 个答案:

答案 0 :(得分:2)

如果您只是想要删除doc_details中没有相应父记录(也称为孤立记录)的记录,那么这样做(这可以通过添加外键约束来避免。请注意以下内容):

delete
from doc_details
where id_doc not in (
   select id_doc from head_doc
)

但是,如果你想要删除两个具有特定id的表中的所有记录,为了清楚起见,最好打破你的删除语句:

delete from doc_details where id_doc = <value>
delete from doc_head where id_doc = <value>

注意:如果您在子表上设置了外键约束,并且您想要删除父表中的记录,则数据库引擎将阻止您删除该记录。如果未首先删除子记录,则为父表。只要有可能,设置外键约束是一个好主意,以确保在删除父记录时不会在子表中显示孤立记录。

答案 1 :(得分:1)

不,在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

或者,我们有时可以通过使用单独的语句从每个表中删除来解决该问题。

我们注意到,由于内部联接操作,问题中的查询只会从head_doc中删除doc_details中具有相关子行的行。如果没有任何子行,这将在head_doc中留下行。这不一定是糟糕的编程。但这有点奇怪。

鉴于您要从两个表中删除行,您可能需要外部连接,因此即使{{1}中不存在匹配的子行,也要从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 = ? ,一个更简单的模式是使用两个单独的DELETE语句,首先从子表中删除,然后从父表中删除:

id_doc

如果 DELETE FROM doc_details WHERE id_doc = ? DELETE FROM head_doc WHERE id_doc = ? 中要删除的行是由head_doc列以外的其他条件标识的,则{{1>中的列我们可以使用JOIN操作来识别子表中应该删除的行

e.g。首先,从子表中删除行(使用JOIN操作)

id_doc

然后,从父表中删除:

doc_details

总之,在DELETE中使用JOIN操作不一定是“编程错误”。我们需要注意一些警告。有时,使用连接操作是最好的方法。这实际上取决于你想要达到的目标。