Delete with Join in MySQL
下面是创建我的表的脚本:
在我的PHP代码中,删除客户机时,我希望删除所有项目日志:
号
posts表没有外键client_id,只有project_id。我想删除已通过client_id的项目中的帖子。
这现在不起作用,因为没有帖子被删除。
- 我认为Yehosef的回答应该是可以接受的,因为他按照您的要求使用join,而且它比yukondude建议的in子句执行得更好…
- 首选模式是DELETE posts FROM posts JOIN projects ...模式,而不是IN (subquery)模式。(Yehosef的答案给出了首选模式的示例。)
- @Gerardogrignoli,它对特定的引擎或MySQL版本的性能更好?这两个查询执行起来没有任何不同的原因,因为afaik是相同的。当然,如果每次我的查询优化器做了一些愚蠢的事情,我都能得到一分钱……
- 您也可以使用alias作为表名并使用它。
您只需指定要从posts表中删除条目:
号
编辑:有关详细信息,您可以查看此备选答案
- 应该注意的是,这是正确的答案,因为联接强制您使用"从日志中删除日志"而不是普通的"从日志中删除",因为要删除的表不再是明确的。谢谢!
- 注意,此处不能使用"as"方法,例如,内部联接项目作为p on p.projectu id…
- 实际上,您可以对联接的表使用别名,但不能对主表(POST)使用别名。"从posts中删除posts inner join projects p on p.project_id=posts.project_id"
- "如果为表声明别名,则在引用表时必须使用别名",就像这样DELETE d FROM posts AS d JOIN projects AS p ON ...。
- 我以前从未用过":"符号。有人能解释一下吗?projects.client_id=:client_id什么是":"?
- 这只是一种表示要替换/转义的变量的方法-请查看php.net/manual/en/pdostatement.bindparam.php中的示例
- 这是最好的答案,因为您甚至可以在一个操作中从两个表中删除DELETE posts , projects FROM posts INNER JOIN projects ON projects.project_id = posts.project_id WHERE projects.client_id = :client_id。
- @Sianopollo"不再含糊不清"和"模棱两可"一样吗?
- @狮子座,你说得对。我的意思是"要删除的表不再含糊不清"。
- 提示:限制不适用于"多表删除"。参见:dev.mysql.com/doc/refman/5.6/en/delete.html
- @tinybyte,如果select *表示全选,为什么delete *不工作?为什么我们必须明确地说出它们的名字?
- @是的,你为什么拒绝编辑?
- @Pacerier看到meta.stackoverflow.com/questions/288352/…和我在那里的评论-我还在考虑。
- @是的,既然你想让我们发布一个新的答案,我已经这样做了。有太多有用的信息要隐藏在回滚下。你可以从你的帖子链接到我下面的帖子。
- @起搏器完成。
- @Yehosef,引用dev.mysql.com/doc/refman/5.6/en/delete.html:"对于第二个多表语法,只删除FROM子句中列出的表中的匹配行(在using子句之前)。他们提出的第二种多表语法是:DELETE FROM t1, t2 USING t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.id=t2.id AND t2.id=t3.id;。那么,为什么我们需要在DELETE后面提到表名呢?
- @pacerier——使用select*时,*表示任何列和所有列。使用"删除"可以删除行。您可能会说*是隐式的,因为它删除了被删除行中的所有列数据。
- @安德烈,不,这是不一样的——"不再含糊"意味着过去是含糊的。模棱两可只是意味着它现在是模棱两可的。两者都可以用作指定表的原因,但前者意味着如果没有额外的联接,就不需要表规范。至于西亚诺波洛,他纠正了自己的陈述错误,并把意思改成了他想要的相反的意思。
因为您选择了多个表,所以要从中删除的表不再是明确的。您需要选择:
在这种情况下,table_name1和table_name2是相同的表,因此这将起作用:
。
如果您想:
注意,order by和LIMIT不适用于多表删除。
还要注意,如果为表声明别名,则在引用表时必须使用别名:
。
地毯吸烟者等的贡献。
- 如果您要给出更好的答案-至少您可以使SQL更具可读性。此问题中的所有其他SQL引用都有大写的关键字(只有一个投票数为0)。我不知道你为什么回复我的编辑。
- @是的,有一群人觉得帽子很炫目。我相信我不是唯一一个,我也见过不少人使用小写。
- 很公平-我尊重你以你喜欢的方式写答案的权利;)
- 你真的不喜欢大写的关键词,是吗?:d我刚才看到你在写《江户记》时,别人会写《江户记》时,你的回答对我有帮助,所以请接受我的赞成票:)
- 为了增加caps/no caps的讨论,事实上,您可以使用您喜欢的任何样式,但在您的答案中,您实际上混合了您认为方便的样式-ON是大写的。对于经验不足的开发人员来说,在风格方面混乱和不一致是可以的。
- @遮阴,抓得好,ON是一个打字错误。我总是把所有关键词放低。答案已编辑。
- caps关键字不明显。它们使查询可读;)
或者同样的事情,使用稍微不同的(imo友好的)语法:
1 2 3
| DELETE FROM posts
USING posts , projects
WHERE projects.project_id = posts.project_id AND projects.client_id = :client_id ; |
顺便说一下,使用mysql时,使用join的速度几乎总是比子查询快…
- 这个用法是什么意思?
- 关于USING的好解释:stackoverflow.com/questions/11366006/mysql-on-vs-using
- @Bigtex777:请注意,在select语句中使用关键字与delete语句中的相同关键字几乎没有关系。在"选择"中,它指定要联接的列的列表,而在"删除"中,它是联接中所有表的列表。
您也可以使用这样的别名,它只在我的数据库中使用!T是需要从中删除的表!
。
- 这对于复合键联接很有用,以避免重复表名
- "实际上,您可以对联接的表使用别名,但不能对主表(posts)使用别名。"从posts中删除posts inner join projects p on p.project_id=posts.project_id'"-@webide
- 实际上(引用dev.mysql.com/doc/refman/5.0/en/delete.html)"如果为表声明别名,则在引用表时必须使用别名:将T1从测试中删除为T1,test2,其中…",因此使用别名很好。
我更习惯这个子查询解决方案,但我没有在MySQL中尝试过:
- 您应该避免在SQL中使用in关键字(尽管对于初学者来说,它通常更容易理解),并使用join代替(如果可能的话),因为子查询通常会使事情慢很多。
- 当子查询返回大量行时,这会导致数据库崩溃。它也非常慢。
- @用户276648和Raj Sekharan是正确的:这是一个缓慢的方法。但我清楚地记得有一个RDBMS引擎拒绝执行包含联接的删除。我希望我能记住哪一个。在任何情况下,我发现,在第一眼就更容易理解,并且除非有可量化的性能问题,否则我会保持原样。
- @实际上,yukondude的"in"比"join"更容易理解,这就是为什么那些不太熟悉SQL的人最终会在"everywhere"中写"in",而他们可以使用"join",它的性能更好(或者说,根据查询,whoole更好)。我记得几年前,几乎所有的SQL查询都会被真正知道如何编写好的查询的人重写。这就是为什么我添加了注释以避免"入",这样人们就会知道,如果可能的话,他们应该避免使用它。
- @用户276648我认为我们基本上是同意的,特别是当涉及到除delete之外的语句时。例如,在select语句中与子查询一起使用会使我难以理解逻辑。但是对于删除,如果这样做没有明显的损害,我愿意让幻灯片进来。
- 对于具有数千或数百万条记录的查询,此子选择将表现不佳。双表联接语法和IN语句一样简单。我的建议是,除非列表中有一组非常小的非动态值,否则永远不要在中使用。
- 我之所以来到这个页面,是因为我用in语句编写的查询速度太慢了。在这里绝对避免被接受的答案。
- 这个方法的另一个问题是您不能在子查询中包含posts表…它引发了一个SQL错误
- 嗯,对于性能不重要的任务,这也是一个很好的、可读的解决方案!
- 尽管这个问题由来已久,但重要的是要知道为什么应该使用join而不是in。当条件在一行上运行时,它将在内部运行该查询。这意味着,如果有100行需要与其中的行进行检查,那么子查询将运行100次。而联接只运行一次。所以,当你的数据库变得越来越大时,完成这个查询需要越来越长的时间。@马库斯只是因为一些不重要的东西并不意味着你应该写错误的代码。写得好一点可以节省你很多时间和将来的头疼。:)
- 只有小数据才有可能
- SQL数据库有一个查询优化器。因此,您认为数据库如何执行查询通常是错误的。Anbody真的知道在当前的MySQL中这个速度会变慢吗?有一些DBMS,当它们具有相同的语义时,在内部只将一种形式转换为。此外,删除操作通常会变慢。而且,不,@kudherm,DBMS不需要根据所有项目ID检查每个日志。当您对项目ID有一个索引时,它可以使用这个索引来查找所有文章。
mysql删除带join的记录
通常,在select语句中使用inner join从其他表中具有相应记录的表中选择记录。我们还可以将inner join子句与delete语句一起使用,从表中删除记录,以及其他表中的相应记录,例如,要从满足特定条件的T1和T2表中删除记录,可以使用以下语句:
号
注意,您将表名T1和T2放在delete和from之间。如果省略T1表,则DELETE语句只删除T2表中的记录,如果省略T2表,则只删除T1表中的记录。
联接条件t1.key=t2.key指定t2表中需要删除的相应记录。
WHERE子句中的条件指定需要删除T1和T2中的哪些记录。
单表删除:
为了从posts表中删除条目:
号
为了从projects表中删除条目:
号
为了从clients表中删除条目:
号
删除多个表:
为了从合并结果中删除多个表中的条目,需要将DELETE后面的表名指定为逗号分隔的列表:
假设您要删除特定客户的所有三个表(posts、projects、clients中的条目:
尝试如下操作:
1 2 3 4
| DELETE posts. *,projects. *
FROM posts
INNER JOIN projects ON projects.project_id = posts.project_id
WHERE projects.client_id = :client_id ; |
1 2 3
| 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); |
号
从一个表中删除记录:
号
从两个表中删除记录:
号
使用比使用IN更好的子选择删除的另一种方法是WHEREEXISTS。
。
使用这个而不是连接的一个原因是,带有JOIN的DELETE禁止使用LIMIT。如果您希望在块中删除以不产生完整的表锁,可以添加LIMIT,使用此DELETE WHERE EXISTS方法。
- 这个查询可以用"别名"来写吗?从语法上看,不太清楚在exists()中的posts与从中删除行的posts是如何相同的。(不管怎么说)
- 我听到了,但是不允许在表中删除别名。子查询中的"posts"必须是完整的表名,这意味着如果要在子select from子句中重新使用该表,则必须在该表中使用别名。
- 本工程:DELETE p FROM posts p WHERE EXISTS ( SELECT 1 FROM projects WHERE projects.client_id = p.client_id);。
如果join不适用于您,您可以尝试此解决方案。它用于在不使用外键+特定的where条件时从T1中删除孤立记录。即从表1中删除具有空字段"代码"且表2中没有记录的记录,并按字段"名称"匹配。
。
试试这个,
号
--请注意,在需要删除的表上不能使用别名。
1 2 3 4 5 6 7 8 9
| 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 |
号