这是创建表的脚本:

CREATE TABLE clients (
   client_i INT(11),
   PRIMARY KEY (client_id)
);
CREATE TABLE projects (
   project_id INT(11) UNSIGNED,
   client_id INT(11) UNSIGNED,
   PRIMARY KEY (project_id)
);
CREATE TABLE posts (
   post_id INT(11) UNSIGNED,
   project_id INT(11) UNSIGNED,
   PRIMARY KEY (post_id)
);


在我的PHP代码中,删除客户端时,我要删除所有项目帖子:

DELETE 
FROM posts
INNER JOIN projects ON projects.project_id = posts.project_id
WHERE projects.client_id = :client_id;


posts表没有外键client_id,只有project_id。我想删除已通过client_id的项目中的帖子。

由于没有帖子被删除,目前无法正常工作。

评论

我认为Yehosef的答案应该被接受,因为他按照您的要求使用Join,并且它的效果比yukondude建议的使用IN子句还要好。

首选模式是DELETE posts FROM posts JOIN项目...,而不是IN(子查询)模式。 (Yehosef的回答给出了首选模式的示例。)

@GerardoGrignoli,对于特定的引擎或MySQL版本,它的性能更好吗?由于AFAIK完全相同,因此没有理由为什么两个查询的执行结果有所不同。当然,如果我每次都精打细算,我的查询优化器都会做一些愚蠢的事情....

您还可以使用别名作为表名,并使用别名。

#1 楼

您只需要指定要从posts表中删除的条目即可:

DELETE posts
FROM posts
INNER JOIN projects ON projects.project_id = posts.project_id
WHERE projects.client_id = :client_id


编辑:有关更多信息,请参见以下替代答案

评论


应当指出,这是正确的答案,因为联接将迫使您使用“ DELETE FROM FROM posts”而不是常规的“ DELETE FROM posts”,因为要删除的表不再是唯一的。谢谢!

– siannopollo
2012年4月12日20:23在

请注意,您不能在此处使用'as'方法,例如内部连接项目在p.project_id上为p ...

– zz子
2012年4月26日在17:01

实际上,您可以对联接表使用别名,但不能对主表(帖子)使用别名。 “从帖子INNER JOIN项目中删除帖子p ON p.project_id = posts.project_id”

– Weboide
2012年5月29日15:44



“例如,如果为表声明别名,则在引用该表时必须使用别名”,如DELETE d FROM帖子AS d JOIN项目AS p ON ...

– KCD
2012年10月30日在22:11

这是最好的答案,因为您甚至可以在一个操作中从两个表中删除DELETE posts,projects FROM posts INNER JOIN projects on projects.project_id = posts.project_id WHERE projects.client_id =:client_id

– er
2014年4月22日在9:52

#2 楼

由于要选择多个表,因此要删除的表不再是唯一的。您需要选择:

DELETE posts FROM posts
INNER JOIN projects ON projects.project_id = posts.project_id
WHERE projects.client_id = :client_id


在这种情况下,table_name1table_name2是同一张表,因此可以使用:

DELETE projects FROM posts INNER JOIN [...]


如果要执行以下操作,甚至可以从两个表中删除:

另外请注意,如果为表声明别名,则在引用表时必须使用别名:
br />来自Carpetsmoker等的贡献

评论


如果您要提供更好的答案-至少可以使SQL更具可读性。此问题中的所有其他SQL参考都具有大写的关键字(具有0票的关键字除外)。我不确定为什么您要还原我的修改。

– Yeehosef
2015年4月13日在10:21

@Yehosef,有一群人发现CAPS确实很刺眼。我相信我不是唯一的一个,我也看到很多人也使用小写字母。

–起搏器
15年4月13日在12:09

足够公平-我尊重您以您喜欢的方式写出您的答案的权利;)

– Yeehosef
15年4月13日在14:02

没错,要添加到大写/无大写讨论中,可以使用任何喜欢的样式,但是在您的答案中,您实际上是在混合使用自己喜欢的样式-大写的ON。对于经验不足的开发人员,它可能表示,在样式方面可以做到凌乱且不一致。

–阴影
16年7月4日在15:08

CAPS关键字不刺眼。他们正在使查询可读;)

– Sachem
17年11月23日在21:18



#3 楼

还是同一件事,语法略有不同(IMO友好): br />

评论


使用是什么意思?

– CMCDragonkai
15年3月30日在0:59

使用的很好解释:stackoverflow.com/questions/11366006/mysql-on-vs-using

–bigtex777
15年4月8日在18:08

@ bigtex777:请注意,SELECT语句中的关键字USING与DELETE语句中的相同关键字无关。在SELECTs中,它指定要连接的列的列表,而在DELETE中,它是连接中所有表的列表

–艾芬豪
15年4月16日在1:29

#4 楼

您也可以像这样使用ALIAS,它可以在我的数据库中使用! t是需要删除的表!

DELETE t FROM posts t
INNER JOIN projects p ON t.project_id = p.project_id
AND t.client_id = p.client_id


评论


这对于复合键联接很有用,以避免重复表名

–马克斯
2014年6月23日19:25



“实际上,您可以对联接表使用别名,但不能对主表(帖子)使用别名。'从帖子中删除帖子INNER JOIN项目p ON p.project_id = posts.project_id'” — @Weboide

–Jeaf Gilbert
14-10-23在9:54

实际上(引自dev.mysql.com/doc/refman/5.0/en/delete.html)“如果为表声明别名,则在引用表时必须使用别名:DELETE t1 FROM test AS t1, test2 WHERE ...”,因此可以使用别名。

–彼得·鲍尔斯(Peter Bowers)
2015年2月25日在7:26

#5 楼

我更习惯于此的子查询解决方案,但是我还没有在MySQL中尝试过它:


评论


您实际上应该避免在SQL中使用IN关键字(即使对于初学者来说通常更容易理解),而应尽可能地使用JOIN,因为子查询通常会使事情变慢。

–user276648
2011-10-28 2:05

当子查询返回大量行时,这往往会使数据库崩溃。它也非常慢。

–拉吉
2012-2-23 15:38

@yukondude确实,“ IN”比起初的“ JOIN”要容易理解很多,这就是为什么对SQL不太熟悉的人最终会到处写“ IN”,而他们可以使用性能更好的“ JOIN”(或更好的whooole,具体取决于查询)。我记得几年前,几乎所有我的SQL查询都将由真正知道如何编写良好查询的人重写。这就是为什么我添加注释以避免使用“ IN”的原因,以便人们知道,如果可能的话,他们应该避免使用它。

–user276648
2012年5月24日9:58

我来到此页面的根本原因是因为我使用IN语句编写的查询非常慢。绝对避免在这里接受答案。

– MikeKulls
2013年6月14日下午2:15

与这个问题一样古老,重要的是要知道为什么要使用JOIN而不是IN。当条件连续运行时,它将在IN内运行该查询。这意味着,如果需要根据WHERE检查100行,则该子查询将运行100次。而JOIN仅运行一次。因此,随着您的数据库越来越大,该查询将花费越来越长的时间才能完成。 @markus仅仅因为不重要的事情并不意味着您应该编写错误的代码。更好地编写它会为您节省很多时间和将来的头痛。 :)

–旭日
2015年3月7日,0:29

#6 楼

单个表删除:

为了从posts表中删除条目:

DELETE ps 
FROM clients C 
INNER JOIN projects pj ON C.client_id = pj.client_id
INNER JOIN posts ps ON pj.project_id = ps.project_id
WHERE C.client_id = :client_id;


为了从projects表中删除条目:

DELETE pj 
FROM clients C 
INNER JOIN projects pj ON C.client_id = pj.client_id
INNER JOIN posts ps ON pj.project_id = ps.project_id
WHERE C.client_id = :client_id;


为了从clients表中删除条目:

DELETE C
FROM clients C 
INNER JOIN projects pj ON C.client_id = pj.client_id
INNER JOIN posts ps ON pj.project_id = ps.project_id
WHERE C.client_id = :client_id;



多个表删除:

为了从联接结果中删除多个表中的条目,您需要在DELETE之后指定表名作为逗号分隔列表:

假设您要从所有表中删除条目特定客户的三个表(postsprojectsclients):

DELETE C,pj,ps 
FROM clients C 
INNER JOIN projects pj ON C.client_id = pj.client_id
INNER JOIN posts ps ON pj.project_id = ps.project_id
WHERE C.client_id = :client_id


#7 楼

使用JOIN的MySQL DELETE记录

通常,您在SELECT语句中使用INNER JOIN从表中选择具有其他表中相应记录的记录。我们还可以将INNER JOIN子句与DELETE语句一起使用,以从表中删除记录以及其他表中的对应记录,例如,从满足特定条件的T1和T2表中删除记录,请使用以下语句: br />
DELETE T1, T2
FROM T1
INNER JOIN T2 ON T1.key = T2.key
WHERE condition


请注意,将表名T1和T2放在了DELETE和FROM之间。如果省略T1表,则DELETE语句仅删除T2表中的记录,而如果省略T2表,则仅删除T1表中的记录。

联接条件T1.key = T2.key指定T2表中需要删除的对应记录。

WHERE子句中的条件指定T1和T2中需要删除的记录。

#8 楼

尝试如下:

DELETE posts.*,projects.* 
FROM posts
INNER JOIN projects ON projects.project_id = posts.project_id
WHERE projects.client_id = :client_id;


#9 楼

使用子选择而不是IN更好的另一种删除方法是WHERE EXISTS禁止使用DELETE。如果希望删除块以免产生完整的表锁,则可以使用此JOIN方法添加LIMIT

评论


可以使用“别名”编写此查询吗?从语法上还不太清楚EXISTS()中的帖子如何与删除行的帖子相同。 (恕我直言)

– MattBianco
2014年10月3日14:18

我听到了您的声音,但是不允许在表中删除别名。子查询中的“帖子”必须是完整的表名,这意味着,如果您想在子选择From子句中重新使用该表,则必须在该表中使用别名。

– Jim Clouse
2014年10月3日在15:12

这是可行的:DELETE p FROM posts p WHERE EXISTS(从项目WHERE projects.client_id = p.client_id中选择1);

– MattBianco
2014年10月6日在6:40

#10 楼

mysql> INSERT INTO tb1 VALUES(1,1),(2,2),(3,3),(6,60),(7,70),(8,80);

mysql> INSERT INTO tb2 VALUES(1,1),(2,2),(3,3),(4,40),(5,50),(9,90);


从一个表中删除记录:

mysql> DELETE tb1 FROM tb1,tb2 WHERE tb1.id= tb2.id;


从两个表中删除记录:

mysql> DELETE tb2,tb1 FROM tb2 JOIN tb1 USING(id);


#11 楼

如果加入对您不起作用,则可以尝试此解决方案。它用于在不使用外键+特定条件的情况下从t1删除孤立记录。即它会从table1中删除记录,这些记录的字段为“ code”为空,并且在table2中没有记录,并按字段“ name”匹配。

#12 楼

试试这个,

DELETE posts.*
FROM posts
INNER JOIN projects ON projects.project_id = posts.project_id
WHERE projects.client_id = :client_id


#13 楼

一种解决方案是使用子查询
DELETE FROM posts WHERE post_id in (SELECT post_id FROM posts p
INNER JOIN projects prj ON p.project_id = prj.project_id 
INNER JOIN clients c on prj.client_id = c.client_id WHERE c.client_id = :client_id 
);

子查询返回需要删除的ID。这三个表都使用联接进行连接,并且仅删除满足过滤条件的那些记录(在您的情况下,即where子句中的client_id)。

#14 楼

-请注意,不能在需要删除的表上使用别名

DELETE tbl_pagos_activos_usuario
FROM tbl_pagos_activos_usuario, tbl_usuarios b, tbl_facturas c
Where tbl_pagos_activos_usuario.usuario=b.cedula
and tbl_pagos_activos_usuario.cod=c.cod
and tbl_pagos_activos_usuario.rif=c.identificador
and tbl_pagos_activos_usuario.usuario=c.pay_for
and tbl_pagos_activos_usuario.nconfppto=c.nconfppto
and NOT ISNULL(tbl_pagos_activos_usuario.nconfppto)
and c.estatus=50