如何从MySQL中的多个表中删除?


116

我正在尝试一次从几个表中删除。我做了一些研究,并提出了

DELETE FROM `pets` p,
            `pets_activities` pa
      WHERE p.`order` > :order
        AND p.`pet_id` = :pet_id
        AND pa.`id` = p.`pet_id`

但是,我收到此错误

未捕获的Database_Exception [1064]:您的SQL语法有错误;检查与您的MySQL服务器版本相对应的手册以获取正确的语法,以在'p,pets_activitiespa ... 附近使用...

我以前从未做过跨表删除操作,所以我现在没有经验,而且一直坚持下去!

我究竟做错了什么?

Answers:


204

JOINDELETE语句中使用a 。

DELETE p, pa
      FROM pets p
      JOIN pets_activities pa ON pa.id = p.pet_id
     WHERE p.order > :order
       AND p.pet_id = :pet_id

或者,您可以使用...

DELETE pa
      FROM pets_activities pa
      JOIN pets p ON pa.id = p.pet_id
 WHERE p.order > :order
   AND p.pet_id = :pet_id

...仅删除 pets_activities

看到这个

对于单表中删除,但具有参照完整性,也有与做的其他方式EXISTSNOT EXISTSINNOT IN等,但上面你来自哪里,用别名来删除该表指定前一个FROM条款可以让你出几个漂亮的紧斑点更容易。我倾向于EXISTS在99%的情况下使用,然后有1%的MySQL语法需要一天的时间。


7
我尝试通过联接6个大表(每个人约〜15,000行)来尝试“全部删除1条查询”,并且该查询花了155秒删除了6个表中的63行:O
KlemenTušar2012年

1
@cadman这是真正的正确答案;可能有人反对使用它,但有时它很有用
Simon Christian

1
+1我同意这是真正正确的答案,因为问题不是“你应该”而是“如何”。但是,我对听到有关1%的信息很感兴趣,因为我无法想到一个首选的情况。
Erick Robertson 2014年

2
@techouse,您是否加入并筛选了索引?15k x 15k x 15k x 15k 15k x 15k是1100万。做了SELECT采取同样长时间?
Paul Draper

6
您还可以使用LEFT JOIN,如果第二张表没有匹配的条目,该功能将非常有用,否则将不会删除任何内容。
Lexib0y 2015年

20

由于这似乎是pets和之间的简单父子关系pets_activities,因此最好使用删除级联来创建外键约束。

这样,当pets删除一行时,pets_activities与其关联的行也会自动删除。

然后,您的查询变得简单:

delete from `pets`
    where `order` > :order
      and `pet_id` = :pet_id

3
@Erick,如果您已设置参照完整性,则级联删除不会比单独删除引起更多麻烦。由于映射,我们已经知道这pa是一个适当的子级。pid/pet_id
paxdiablo

14
嗯,你们有自己的想法,但是似乎您在贬低DBMS的许多功能。级联删除与触发器,存储过程或约束一样,也是数据管理的一部分,并且只有在您不知道自己在做什么的情况下它们才是危险的。不过,我不会进一步争论这一点,我们只需要同意不同意。
paxdiablo

8
埃里克,现在你引起了我的兴趣。您如何确保数据库中的数据完整性不受限制?
paxdiablo

4
@Erick说:“我也不使用触发器,存储过程或约束。” 嗯,您使用Excel。:-)
james.garriss

4
我只想跟进此事。在这种情况下,我已更改了删除级联的立场。我参与了一个新的SQL环境,该环境使用了它们,并很好地使用了它们,并且它们非常有组织。在此系统中,将这些级联安装到位对于我们的优势非常有效。它当然可以防止孤立数据,并且没有危险。问题是使用数据库的每个人都需要了解如何安全地使用它们。但是,当初级开发人员在无人监督的情况下进行数据库更改时,总会有风险。
艾里克·罗伯逊


3

我目前没有要测试的mysql数据库,但是您是否尝试在from子句之前指定要删除的内容?例如:

DELETE p, pa FROM `pets` p,
        `pets_activities` pa
  WHERE p.`order` > :order
    AND p.`pet_id` = :pet_id
    AND pa.`id` = p.`pet_id`

我认为您使用的语法仅限于较新版本的mysql。


1
该查询已成功执行,但是并没有删除任何行(但我相信应该有)。
Alex


1

对于2017年阅读此书的人来说,这就是我做类似事情的方式。

DELETE pets, pets_activities FROM pets inner join pets_activities
on pets_activities.id = pets.id WHERE pets.`order` > :order AND 
pets.`pet_id` = :pet_id

通常,要从多个表中删除行,请遵循以下语法。该解决方案基于两个表之间存在某种联系的假设。

DELETE table1, table2 FROM table1 inner join table2 on table2.id = table1.id
WHERE [conditions]

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.