【问题标题】:Deleting rows from SQLite table when no match exists in another table当另一个表中不存在匹配项时从 SQLite 表中删除行
【发布时间】:2011-06-25 10:13:16
【问题描述】:

我需要从 SQLite 表中删除行 ID 不存在于另一个表中的行。 SELECT 语句返回正确的行:

SELECT * FROM cache LEFT JOIN main ON cache.id=main.id WHERE main.id IS NULL;

但是,delete 语句会从 SQLIte 生成错误:

DELETE FROM cache LEFT JOIN main ON cache.id=main.id WHERE main.id IS NULL;

错误是:SQLite 错误 1 ​​- 在“左”附近:语法错误。我可以使用其他语法吗?

【问题讨论】:

  • 解释一下:我正在使用附加的 where 条件从“主”表中删除行,以保留用户标记为“锁定”的任何行(即,在解锁之前不应删除):DELETE FROM 主 WHERE id = ? AND 锁定 = 0;每次成功删除后都必须从“缓存”表中删除匹配行,但 SQlite 不会返回一个值,让我知道第一个删除语句是否实际匹配任何行。因此,我尝试从缓存表中删除“不匹配”的行,并在左连接上遇到问题。

标签: sqlite left-join sql-delete


【解决方案1】:

@wimvds 的解决方案对我不起作用,因此我修改了查询并删除了 WHERE 条件:

DELETE FROM FirstTable WHERE firstTableId NOT IN (SELECT SecondTable.firstTableId FROM SecondTable LEFT JOIN FirstTable ON FirstTable.firstTableId=SecondTable.firstTableId)

这会从 FirstTable 中删除所有未将其 id 分配给 SecondTable 中的任何行的行。

【讨论】:

    【解决方案2】:

    SQLite 显然不支持使用 delete 语句进行连接,正如您在 Syntax diagrams 上看到的那样。但是,您应该能够使用子查询来删除它们。

    即。

    DELETE FROM cache WHERE id IN
    (SELECT cache.id FROM cache LEFT JOIN main ON cache.id=main.id WHERE main.id IS NULL);
    

    (未测试)

    【讨论】:

    • 谢谢!在阅读您的答案之前,我已经非常接近这一点,除了我使用的是 equals 而不是 IN,所以我的尝试并没有按预期工作。
    【解决方案3】:

    既然走子查询的路线,不如干脆去掉join,简化查询:

    DELETE FROM cache WHERE id NOT IN (SELECT id from main);
    

    【讨论】:

    • 如果main 包含数百万行,则不是理想的解决方案。最好先加入。
    • @Jacob 希望一开始没有人在 sqlite 中做数百万行。
    • 如果您的表没有主键,您可以即时破解一个,例如:DELETE FROM cache WHERE x || ',' || y NOT IN (SELECT x || ',' || y from main);
    • @fluffy,不要低估 SQLite :) 使用它来处理数百万行是完全合理的,但即使是几千行,这个 SELECT id FROM 查询也不必要地低效和缓慢。 @winvds 答案是一个更好的选择。
    猜你喜欢
    • 2018-10-16
    • 2011-03-23
    • 1970-01-01
    • 1970-01-01
    • 2014-12-26
    • 2020-09-16
    • 1970-01-01
    • 2011-04-26
    • 2022-01-21
    相关资源
    最近更新 更多