如何使用Where子句从多个表中删除多行?

时间:2015-08-31 16:35:47

标签: java sql oracle jdbc prepared-statement

使用Oracle DB,我需要从存在条件的表中选择所有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();

有更好/更有效的方式吗?

3 个答案:

答案 0 :(得分:2)

如果3个表中的两个(例如“table2”和“table3”)是具有“ON DELETE CASCADE”的父表(例如“table1”)的子表,则可以使用一个DELETE语句执行此操作选项。

这意味着这两个子表有一个列(“table2”和“table3”的示例列“id”),它具有带有“ON DELETE CASCADE”选项的外键约束,该选项引用父键的主键列table(“table1”的示例列“id”)。这样,只从父表中删除会自动删除子表中的关联行。

更详细地查看此内容:http://www.techonthenet.com/oracle/foreign_keys/foreign_delete.php

答案 1 :(得分:1)

如果只删除大表的少数记录,请确保索引就可以了 列ID已定义。

要从表TABLE2和表3中删除记录,最好的策略是使用提议的CASCADE DELETE @ivanzg - 如果无法做到这一点,请参见下文。

要从TABLE1中删除基于行的批量删除的更优越的选项,请使用基于年龄的谓词进行符号删除:

 PreparedStatement stmt = con.prepareStatement("DELETE FROM TABLE1 WHERE age > ?")
 stmt.setInt(1,60)
 Integer rowCount = stmt.executeUpdate()

如果你不能级联删除,请使用table2和3与上面相同的概念,但使用以下语句:

 DELETE FROM TABLE2/*or 3*/ WHERE ID in (SELECT ID FROM TABLE1 WHERE age > ?)

一般最佳实践 - 客户端中的最小逻辑,数据库服务器中的整个逻辑。数据库应该能够做出合理的执行计划 - 见上面的索引说明。

答案 2 :(得分:0)

DELETE statement按语句操作表。但是,主要实现支持执行从属修改的触发器或其他机制。例如Oracle's CREATE TRIGGER

然而,开发人员最终可能会弄清楚数据库在他们背后做了什么。 (When/Why to use Cascading in SQL Server?

或者,如果您需要在删除语句中使用中间结果。您可以在批处理中使用时态表(如建议的here)。

作为旁注,我在示例代码中看不到事务控制(setAutoCommit(false) ... commit()。我想这可能是为了简单起见。

此外,您正在执行3个不同的删除批处理(每个表一个)而不是一个。这可能会否定使用PreparedStatement的好处。