如何使用 Where 子句从多个表中删除多行?
Posted
技术标签:
【中文标题】如何使用 Where 子句从多个表中删除多行?【英文标题】:How to delete multiple rows from multiple tables using Where clause? 【发布时间】:2015-08-31 16:35:46 【问题描述】:使用 Oracle 数据库,我需要从存在条件的表中选择所有 ID,然后从存在该 ID 的多个表中删除行。伪代码类似于:
SELECT ID FROM TABLE1 WHERE AGE > ?
DELETE FROM TABLE1 WHERE ID = <all IDs received from SELECT>
DELETE FROM TABLE2 WHERE ID = <all IDs received from SELECT>
DELETE FROM TABLE3 WHERE ID = <all IDs received from SELECT>
最好和最有效的方法是什么?
我正在考虑类似以下的事情,但想知道是否有更好的方法。
PreparedStatement selectStmt = conn.prepareStatment("SELECT ID FROM TABLE1 WHERE AGE > ?");
selectStmt.setInt(1, age);
ResultSet rs = selectStmt.executeQuery():
PreparedStatement delStmt1 = conn.prepareStatment("DELETE FROM TABLE1 WHERE ID = ?");
PreparedStatement delStmt2 = conn.prepareStatment("DELETE FROM TABLE2 WHERE ID = ?");
PreparedStatement delStmt3 = conn.prepareStatment("DELETE FROM TABLE3 WHERE ID = ?");
while(rs.next())
String id = rs.getString("ID");
delStmt1.setString(1, id);
delStmt1.addBatch();
delStmt2.setString(1, id);
delStmt2.addBatch();
delStmt3.setString(1, id);
delStmt3.addBatch();
delStmt1.executeBatch();
delStmt2.executeBatch();
delStmt3.executeBatch();
有没有更好/更有效的方法?
【问题讨论】:
你用的是什么关系型数据库? 你可以使用WHERE id IN (...)
在 for 循环中多次向数据库发送命令而不是发送一次更愚蠢,而且性能大大提高。如果性能(效率)不是您的目标,那么就这样做吧。
它不是标签,它是我问题的重要部分。我在问如何在 Java 中做这个特殊的事情。同样,这已经在标签中说明了。无需在标题中添加标签。而且,最后,你只是在执行普通的 sql 语句......
【参考方案1】:
如果您的 3 个表中的两个(例如“table2”和“table3”)是具有“ON DELETE CASCADE”的父表(例如“table1”)的子表,您可以使用一个 DELETE 语句执行此操作选项。
这意味着两个子表有一个列(例如“table2”和“table3”的列“id”),该列具有引用父主键列的“ON DELETE CASCADE”选项的外键约束表(“table1”的示例列“id”)。这样只有从父表中删除才会自动删除子表中的关联行。
查看更多详细信息:http://www.techonthenet.com/oracle/foreign_keys/foreign_delete.php
【讨论】:
【参考方案2】:如果只删除大表中的几条记录,请确保 列 ID 已定义。
要从表 TABLE2 和 3 中删除记录,最好的策略是使用 CASCADE DELETE,如 @ivanzg - 如果这不可能,请参见下文。
要从 TABLE1 中删除一个基于行的批量删除的优越选项,请使用基于年龄的谓词使用signle delete:
PreparedStatement stmt = con.prepareStatement("DELETE FROM TABLE1 WHERE age > ?")
stmt.setInt(1,60)
Integer rowCount = stmt.executeUpdate()
如果不能级联删除,则表2和表3使用与上述相同的概念,但语句如下:
DELETE FROM TABLE2/*or 3*/ WHERE ID in (SELECT ID FROM TABLE1 WHERE age > ?)
一般最佳实践 - 客户端中的最小逻辑,数据库服务器中的整个逻辑。数据库应该能做合理的执行计划 - 见上面的索引说明。
【讨论】:
【参考方案3】:DELETE statement 每个语句操作一个表。然而,主要实现支持触发器或其他执行从属修改的机制。例如Oracle's CREATE TRIGGER。
但是,开发人员最终可能会弄清楚数据库在背后做什么。 (When/Why to use Cascading in SQL Server?)
或者,如果您需要在删除语句中使用中间结果。您可以在批处理中使用时态表(如建议的here)。
附带说明,我在您的示例代码中看不到事务控制(setAutoCommit(false)
... commit()
。我想这可能是为了简单起见。
此外,您正在执行 3 个不同的删除批次(每个表一个)而不是一个。这可能会抵消使用PreparedStatement
的好处。
【讨论】:
以上是关于如何使用 Where 子句从多个表中删除多行?的主要内容,如果未能解决你的问题,请参考以下文章
如何在从多个表中获取多行的同时删除 sql JOIN 中的重复项
如何使用引用多个表的 WHERE 子句删除 sqlite 中的行?
如何选择具有多个选择值的数据作为 where 子句? - Ajax Codeigniter