SQL DELETE 带有 INNER JOIN

142

有两张表,spawnlistnpc,我需要从spawnlist删除数据。 npc_templateid = n.idTemplate是"连接"这两个表的唯一条件。

我尝试了这个脚本,但它没有起作用:

DELETE s FROM spawnlist s
INNER JOIN npc n ON s.npc_templateid = n.idTemplate
WHERE (n.type = "monster");

1
更让人惊讶的是,通常L2社区都保持独立。不过看到这个问题时有点奇怪,心想“这看起来像...嗯...就是它!” :) - Corbin
1
@Corbin 我完全明白你的意思。有趣的是,我正在为一个工作项目寻求L2问题的帮助。 - Marco Aurélio Deleu
3个回答

256
在你的第一行中,将s添加.*
尝试:
DELETE s.* FROM spawnlist s
INNER JOIN npc n ON s.npc_templateid = n.idTemplate
WHERE (n.type = "monster");

我只是在这里粘贴时犯了一个错误,但用户名和数据库名称是相同的,在我的错误中。 - JoinOG
尝试为您的别名添加 AS - ThinkingStiff
[错误] 1064 - 您的SQL语法有误;请检查与您的MySQL服务器版本相对应的手册,以获取正确的语法使用方式。位于第1行附近的代码为:'spawnlist FROM InnoDB.root.spawnlist AS s INNER JOIN InnoDB.root.npc AS n ON' - JoinOG
你正在运行哪个版本的MySQL? - ThinkingStiff
4
@s.* 告诉 MySQL 要删除什么,你不想从连接的表中删除行。 - Julz
显示剩余9条评论

14
如果数据库是InnoDB,则使用外键和级联删除可能是一个更好的选择,这将实现所需的功能,并且不会存储冗余数据。
对于这个例子,我认为您不需要第一个s。
DELETE s 
FROM spawnlist AS s 
INNER JOIN npc AS n ON s.npc_templateid = n.idTemplate 
WHERE n.type = "monster";

最好在删除之前先选择行,这样您就可以确保要删除的是您想要的内容:

SELECT * FROM spawnlist
INNER JOIN npc ON spawnlist.npc_templateid = npc.idTemplate
WHERE npc.type = "monster";

你还可以在这里查看MySQL的删除语法:http://dev.mysql.com/doc/refman/5.0/en/delete.html


如果您只想运行一次,可以运行效率极低的命令:DELETE FROM spawnlist WHERE npc_templateid IN (SELECT idTemplate from npc WHERE type = "monster"); - Corbin
哦,:( 从InnoDB表中删除数据真的很难 :( - JoinOG
还没有成功吗?为什么不设置一个外键,当你从一个表中删除时,使用级联自动删除另一个表中的数据呢? - Dan
嗯,有可能编写一个代码,可以删除两个表中的数据吗?因为我之后可以恢复其中一个。你能帮忙吗? - JoinOG
你可以创建一个包含两个表的视图,然后从视图中删除 type = "monster" 的记录。 - Dan
显示剩余6条评论

6
如果数据库是InnoDB,您不需要在删除操作中进行联接。只需:
DELETE FROM spawnlist WHERE spawnlist.type = "monster";

可以用于删除与其他表中的外键相关联的所有记录,为此您必须首先在设计时间将表链接起来。

CREATE TABLE IF NOT EXIST spawnlist (
  npc_templateid VARCHAR(20) NOT NULL PRIMARY KEY

)ENGINE=InnoDB;

CREATE TABLE IF NOT EXIST npc (
  idTemplate VARCHAR(20) NOT NULL,

  FOREIGN KEY (idTemplate) REFERENCES spawnlist(npc_templateid) ON DELETE CASCADE

)ENGINE=InnoDB;

如果您使用MyISAM,可以像这样连接删除记录。
DELETE a,b
FROM `spawnlist` a
JOIN `npc` b
ON a.`npc_templateid` = b.`idTemplate`
WHERE a.`type` = 'monster';

在第一行,我初始化了两个临时表来删除记录, 在第二行,我将存在表分配给a和b,但在这里我使用join关键字将两个表链接在一起, 并且我匹配了两个表的主键和外键以建立联系, 在最后一行,我通过字段过滤记录以进行删除。


“type” 实际上在另一个表中,而不是在 “spawnlist” 表中,因此需要进行连接。 - vitro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接