如何使用 Where 子句从多个表中删除多行?
How to delete multiple rows from multiple tables using Where clause?
使用 Oracle 数据库,我需要 select 存在条件的 table 中的所有 ID,然后删除存在该 ID 的多个 table 中的行。伪代码类似于:
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();
有better/more有效的方法吗?
DELETE statement operates a table per statement. However the main implementations support triggers or other mechanisms that perform subordinate modifications. For example Oracle's CREATE TRIGGER。
然而,开发人员最终可能会弄清楚数据库在他们背后做了什么。 (When/Why to use Cascading in SQL Server?)
或者,如果您需要在删除语句中使用中间结果。您可以在批处理中使用时间 table(建议 here)。
附带说明一下,我在您的示例代码中没有看到事务控制(setAutoCommit(false)
... commit()
。我想这可能是为了简单起见。
您还执行了 3 个不同的删除批次(每个 table 一个)而不是一个。这可能会抵消使用 PreparedStatement
.
的好处
如果您的 3 个 table 中的两个(例如 "table2" 和 "table3")是父 table 的子 table,则您可以使用一个 DELETE 语句来完成table(例如 "table1")具有 "ON DELETE CASCADE" 选项。
这意味着两个子 table 有一个列(例如 "table2" 和 "table3" 的列 "id")具有外键约束 "ON DELETE CASCADE" 选项引用父 table 的主键列(例如 "table1" 的列 "id")。这样,仅从父 table 中删除会自动删除子 table 中的关联行。
查看更多详细信息:http://www.techonthenet.com/oracle/foreign_keys/foreign_delete.php
如果只删除大 tables 中的几条记录,请确保
列 ID 已定义。
要从 table 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()
如果您不能级联删除,请对 table2 和 3 使用与上述相同的概念,但使用以下语句:
DELETE FROM TABLE2/*or 3*/ WHERE ID in (SELECT ID FROM TABLE1 WHERE age > ?)
一般最佳实践 - 客户端中的最少逻辑,数据库服务器中的全部逻辑。数据库应该能做合理的执行计划
- 见上面的索引说明。
使用 Oracle 数据库,我需要 select 存在条件的 table 中的所有 ID,然后删除存在该 ID 的多个 table 中的行。伪代码类似于:
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();
有better/more有效的方法吗?
DELETE statement operates a table per statement. However the main implementations support triggers or other mechanisms that perform subordinate modifications. For example Oracle's CREATE TRIGGER。
然而,开发人员最终可能会弄清楚数据库在他们背后做了什么。 (When/Why to use Cascading in SQL Server?)
或者,如果您需要在删除语句中使用中间结果。您可以在批处理中使用时间 table(建议 here)。
附带说明一下,我在您的示例代码中没有看到事务控制(setAutoCommit(false)
... commit()
。我想这可能是为了简单起见。
您还执行了 3 个不同的删除批次(每个 table 一个)而不是一个。这可能会抵消使用 PreparedStatement
.
如果您的 3 个 table 中的两个(例如 "table2" 和 "table3")是父 table 的子 table,则您可以使用一个 DELETE 语句来完成table(例如 "table1")具有 "ON DELETE CASCADE" 选项。
这意味着两个子 table 有一个列(例如 "table2" 和 "table3" 的列 "id")具有外键约束 "ON DELETE CASCADE" 选项引用父 table 的主键列(例如 "table1" 的列 "id")。这样,仅从父 table 中删除会自动删除子 table 中的关联行。
查看更多详细信息:http://www.techonthenet.com/oracle/foreign_keys/foreign_delete.php
如果只删除大 tables 中的几条记录,请确保 列 ID 已定义。
要从 table 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()
如果您不能级联删除,请对 table2 和 3 使用与上述相同的概念,但使用以下语句:
DELETE FROM TABLE2/*or 3*/ WHERE ID in (SELECT ID FROM TABLE1 WHERE age > ?)
一般最佳实践 - 客户端中的最少逻辑,数据库服务器中的全部逻辑。数据库应该能做合理的执行计划 - 见上面的索引说明。