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
的项目中的帖子。由于没有帖子被删除,目前无法正常工作。
#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_name1
和table_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
之后指定表名作为逗号分隔列表:假设您要从所有表中删除条目特定客户的三个表(
posts
,projects
,clients
):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
评论
我认为Yehosef的答案应该被接受,因为他按照您的要求使用Join,并且它的效果比yukondude建议的使用IN子句还要好。首选模式是DELETE posts FROM posts JOIN项目...,而不是IN(子查询)模式。 (Yehosef的回答给出了首选模式的示例。)
@GerardoGrignoli,对于特定的引擎或MySQL版本,它的性能更好吗?由于AFAIK完全相同,因此没有理由为什么两个查询的执行结果有所不同。当然,如果我每次都精打细算,我的查询优化器都会做一些愚蠢的事情....
您还可以使用别名作为表名,并使用别名。