我有3个表,第一个,table1,作为主键的id列,第二个表(table2)有一个列table1_id,它作为table1.id的外键引用,第三个表(table3)有,作为table2,列table1_id,作为table1.id的外键引用。
我必须从table1中删除table1.id不在table2.table1_id中的所有行,而不是table3.table1_id
现在我正在使用此查询:
DELETE FROM table1
WHERE table1.id IN (SELECT table1.id
FROM (table2
RIGHT OUTER JOIN table1
ON table2.table1_id = table1.id)
LEFT OUTER JOIN table3
ON table3.table1_id = table1.id
WHERE table2.table1_id IS NULL
AND table3.table1_id IS NULL);
但它很慢,需要花费很多时间,还有一些更好的方法来处理这个删除语句吗?
如果这可以帮助我可以假设table2有更多数据表3。
我使用的数据库是Apache Derby。
感谢您的帮助。
答案 0 :(得分:1)
假设您有明显的覆盖(为table1.id
,table2.table1_id
和table3.table1_id
创建的索引),您不需要执行完全外连接来测试密钥是否在另一个表格,您可以在案例中使用子查询和exists()
- 或not exists()
。
由于您只是测试存在,您可以使用以下模式:
where not exists ( select top 1 1 from... where... )
答案 1 :(得分:1)
DELETE table1
FROM table1
LEFT JOIN table2 ON table1.id = table2.table1_id
LEFT JOIN table3 ON table1.id = table3.table1_id
WHERE table2.table1_id IS NULL
AND table3.table1_id IS NULL
答案 2 :(得分:0)
DELETE from table1
WHERE
table1_id NOT IN (SELECT table1_id FROM table2)
AND
table1_id NOT IN (SELECT table1_id FROM table3)
答案 3 :(得分:0)
您知道要删除多少行?我同意@Blindy,如果德比支持它,那么在你的情况下不存在可能会更好(我不知道德比,所以我不能肯定地说)。但是,如果有大量记录被删除,您可能希望批量执行此操作。无论查询多么有效,删除10,000,000条记录都需要很长时间。在一次执行1000次的循环中删除它们对于数据库来说通常更好,因为它不会占用表锁并在整个过程完成时锁定用户。我再也不知道Derby,所以我不知道Derby是否属实,但它肯定会帮助我熟悉的大多数数据库中的大量删除。