使用JDBC从Oracle 11g中删除记录

时间:2016-02-05 07:27:10

标签: java sql oracle jdbc

我需要从包含900万条记录的表中删除10 000条记录。要删除的ID将从复杂查询中获取并存储在Java集合中。

我有3种方法来实现这个

1)创建一个预准备语句并向批处理添加10000个语句并执行它。

语句将如下所示

Delete from <table_name> where id=?;

2)写一个'in'查询而不是批量使用'='。 像

在此下,可以在Java代码中将10 000个ID创建为逗号分隔值并添加到查询中。或者,将10000个ID插入临时表中,并在子查询中从该表中进行选择。

Delete from <table_name> where id in (<CSV>);
                 or
Delete from <table_name> where id in (select id from <temp_table>);

表中没有约束和索引。而且我无法添加一个,因为我正在使用现有的桌子。

第一个选择是需要很长时间才能完成。它运行了15个小时但仍未完成。

4 个答案:

答案 0 :(得分:2)

您的第一个版本的限制值为1000,并且往往效果不佳。第二种方法可能表现更好,但你必须有一个全局临时表,并填充它是一个额外的步骤。

您可以将Java集合转换为Oracle集合。您可以为此创建自己的表类型,但有一些内置的类型,如ODCINUMBERLIST,您可以在此处使用。你可以把它作为一个表格收集exprssion。

根据您的Java集合类型,细节可能略有不同,但大纲如下:

ArrayDescriptor aDesc = ArrayDescriptor.createDescriptor("SYS.ODCINUMBERLIST",
  conn);
oracle.sql.ARRAY oraIDs = new oracle.sql.ARRAY(aDesc, conn, yourJavaCollectinOfIDs);

cStmt = (OracleCallableStatement) conn.prepareCall(
  "Delete from <table_name> 
   where id in (select column_value from table(?))");
cStmt.setArray(1, oraIDs);
cStmt.execute();

除非它已经是一个简单的数组,否则您需要将Java集合转换为调用中的数组;例如如果你正在使用名为yourArrayList的ArrayList,你可以这样做:

oracle.sql.ARRAY oraIDs = new oracle.sql.ARRAY(aDesc, conn, yourArrayList.toArray());

您仍然会遇到缺少主键或索引的问题,但它会让Oracle有更好的机会来优化它而不是CSV列表(或者多个CSV列表一起OR'd,因为您有超过1000个ID)。 / p>

答案 1 :(得分:1)

您不应该通过从java代码执行10000语句来使用第一个选项。

创建临时表是个好主意。但大多数情况下,您不能拥有超过1000个项目的IN (...)子句。因此,使用CSV的方法可能不会成功。

你可以去

Delete from <table_name> where id in (select id from <temp_table>);

但这种方式也没有优化。最好将delete语句更改为:

Delete from <table_name> m where exists (select id from <temp_table> t where m.id = t.id);

但是,如果您经常进行此类操作,强烈建议您向<table_name>甚至是<temp_table>添加一些约束和索引。它会像魅力一样提升您的运营执行时间。

答案 2 :(得分:0)

WHERE ... IN(...)是要走的路。

IN子句可以引用您已填充的临时表(您的原始想法),或者它可以包含任何选定(固定)的数量?参数。它会将db往返的数量减少一个等于所选数字的因子,但不一定是一个。迭代你的集合并以块的形式处理它。

答案 3 :(得分:0)

试试这样。

Delete from <table_name> where
    id in (1, 2, 3, ... ,1000)
    or id in (1001, 1002, ... , 2000)
    ....