从子选择中删除id为comming的行(使用SQLite,使用MySQL失败)

从子选择中删除id为comming的行(使用SQLite,使用MySQL失败),mysql,sqlite,Mysql,Sqlite,我有两张桌子:桌上的“游戏”和桌上的“玩家”。玩家通过游戏id引用游戏。一个游戏可以包含多个玩家。我的应用程序应该与MySQL和SQLite一起工作,我不在这些表上使用外键 我的应用程序允许通过删除游戏表中的一行来删除游戏。所以,一些玩家可能有一个参考(游戏id)到一个不再存在的游戏,这对我来说很好 现在我想删除“孤儿”玩家:任何出现在玩家身上的无效游戏ID都必须被删除。如果可能的话,我想在一个查询中完成它 我找到了一个使用SQLite的有效解决方案: delete from play

我有两张桌子:桌上的“游戏”和桌上的“玩家”。玩家通过游戏id引用游戏。一个游戏可以包含多个玩家。我的应用程序应该与MySQL和SQLite一起工作,我不在这些表上使用外键

我的应用程序允许通过删除游戏表中的一行来删除游戏。所以,一些玩家可能有一个参考(游戏id)到一个不再存在的游戏,这对我来说很好

现在我想删除“孤儿”玩家:任何出现在玩家身上的无效游戏ID都必须被删除。如果可能的话,我想在一个查询中完成它

我找到了一个使用SQLite的有效解决方案:

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兼容?”