从子选择中删除id为comming的行(使用SQLite,使用MySQL失败)
我有两张桌子:桌上的“游戏”和桌上的“玩家”。玩家通过游戏id引用游戏。一个游戏可以包含多个玩家。我的应用程序应该与MySQL和SQLite一起工作,我不在这些表上使用外键 我的应用程序允许通过删除游戏表中的一行来删除游戏。所以,一些玩家可能有一个参考(游戏id)到一个不再存在的游戏,这对我来说很好 现在我想删除“孤儿”玩家:任何出现在玩家身上的无效游戏ID都必须被删除。如果可能的话,我想在一个查询中完成它 我找到了一个使用SQLite的有效解决方案:从子选择中删除id为comming的行(使用SQLite,使用MySQL失败),mysql,sqlite,Mysql,Sqlite,我有两张桌子:桌上的“游戏”和桌上的“玩家”。玩家通过游戏id引用游戏。一个游戏可以包含多个玩家。我的应用程序应该与MySQL和SQLite一起工作,我不在这些表上使用外键 我的应用程序允许通过删除游戏表中的一行来删除游戏。所以,一些玩家可能有一个参考(游戏id)到一个不再存在的游戏,这对我来说很好 现在我想删除“孤儿”玩家:任何出现在玩家身上的无效游戏ID都必须被删除。如果可能的话,我想在一个查询中完成它 我找到了一个使用SQLite的有效解决方案: delete from play
delete
from
player
where
player_id in (
select
P.player_id
from player P
left join game G on G.game_id = P.game_id
where G.game_id is null
)
但MySQL中的同一查询返回一个错误:
#1093 - You can't specify target table 'player' for update in FROM clause
如果in子句包含同一表中的引用,则似乎无法删除表中的记录
如何在一个与MySQL和SQLite兼容的查询中实现这一点
更改您的
删除
查询,如下所示:
delete
from
player
where
player_id in (
select * from (
select
P.player_id
from player P
left join game G on G.game_id = P.game_id
where G.game_id is null
) as t
)
原因是无法处理锁定删除的表。使用上述技巧,Mysql创建一个临时表,并允许处理Delete命令。两个选项是可能的
使用额外的子查询
查询
delete
from
player
where
player_id in (
select
player_alias.player_id
from (
select
P.player_id
from player P
left join game G on G.game_id = P.game_id
where G.game_id is null
) AS player_alias
)
DELETE
player.*
FROM (
select
P.player_id
from player P
left join game G on G.game_id = P.game_id
where G.game_id is null
) AS player_delete
INNER JOIN
player
ON
player.player_id = player_delete.player_id
delete
P.*
from
player P
left join game G on G.game_id = P.game_id
where G.game_id is null
看
或者使用联接执行“多个”表删除,我会选择这样做,因为使用正确的索引优化查询会更好
查询
delete
from
player
where
player_id in (
select
player_alias.player_id
from (
select
P.player_id
from player P
left join game G on G.game_id = P.game_id
where G.game_id is null
) AS player_alias
)
DELETE
player.*
FROM (
select
P.player_id
from player P
left join game G on G.game_id = P.game_id
where G.game_id is null
) AS player_delete
INNER JOIN
player
ON
player.player_id = player_delete.player_id
delete
P.*
from
player P
left join game G on G.game_id = P.game_id
where G.game_id is null
看
两次删除都将保留
| player_id | name | game_id |
|-----------|------------|---------|
| 111 | PlayerOne | G1 |
| 222 | Player Two | G1 |
编辑
使用联接的“多”表删除可以重写(更)简单的offcource作为额外的加号,这对性能和内存来说也是更好的。假设MySQL可以使用正确的索引来进行查询,因为
FROM(SELECT..)as)也会迫使MySQL将其作为
查询
delete
from
player
where
player_id in (
select
player_alias.player_id
from (
select
P.player_id
from player P
left join game G on G.game_id = P.game_id
where G.game_id is null
) AS player_alias
)
DELETE
player.*
FROM (
select
P.player_id
from player P
left join game G on G.game_id = P.game_id
where G.game_id is null
) AS player_delete
INNER JOIN
player
ON
player.player_id = player_delete.player_id
delete
P.*
from
player P
left join game G on G.game_id = P.game_id
where G.game_id is null
请参见谢谢您的帮助。最新的查询不适用于SQLite,因此我使用了select in select技巧。“最新的查询不适用于SQLite”哦,是的@JayMore I mist“我如何在一个查询中实现这一点,并与MySQL和SQLite兼容?”