使用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();
有更好/更有效的方式吗?
答案 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
的好处。