批量插入:有没有办法在违反约束时跳过下一条记录?

时间:2015-05-21 18:13:13

标签: oracle mybatis

我正在使用mybatis在oracle DB上执行大量批量插入。

我的过程非常简单:我从文件列表中获取记录,并在对数据执行某些检查后将它们插入到特定的表中。

- 每个文件平均包含180.000条记录,我可以拥有多个文件。

- 某些记录可以出现在多个文件中。

- 如果每列匹配,则记录与另一个记录相同,换句话说,我不能简单地对特定字段执行检查。我已在我的数据库中定义了一个约束,以确保满足此条件。

简单地说,我想忽略Oracle在违反约束的情况下会给我的约束异常。

记录不存在? - >插入

记录已存在? - >继续

这可能是mybatis吗?或者我可以在DB级别完成某些事情吗?

我可以控制Application Server和DB,所以请告诉我完成此任务的最有效方法是什么(即使我希望避免过多依赖DB ...)< / p>

当然,我希望在每次插入之前避免执行select * ...考虑到我处理的记录数量会破坏我的应用程序的性能

3 个答案:

答案 0 :(得分:4)

使用IGNORE_ROW_ON_DUPKEY_INDEX提示:

insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(table_name index_name) */
into table_name
select * ...

答案 1 :(得分:3)

我不确定JDBC,但至少在OCI中它是可能的。使用批处理操作,您可以将向量作为绑定变量传递,并且还可以返回返回ID的向量以及错误代码向量。

  • 您还可以在数据库服务器端使用MERGE以及custon集合类型。类似的东西:

    merge into t

    using ( select * from TABLE(:var) v)

    on ( v.id = t.id )

    when not matched then insert ...

其中:var是SQL类型的绑定变量:TABLE OF <recordname> 单词"TABLE"是一个用于从绑定变量转换为表格的构造。

  • 另一种选择是使用SQL error loggin子句:

    DBMS_ERRLOG.create_error_log (dml_table_name => 't');

    insert into t(...) values(...) log errors reject limit unlimited;

然后在加载后,您将不得不截断错误记录表错误$ _t;

与使用sqlldr相比,看起来任何解决方案都要做很多工作。

答案 2 :(得分:1)

忽略带有错误表的错误

insert 
into table_name
select * 
from selected_table
LOG ERRORS INTO SANJI.ERROR_LOG('some comment' ) 
                    REJECT LIMIT UNLIMITED;

,错误表架构为:

CREATE GLOBAL TEMPORARY  TABLE SANJI.ERROR_LOG (
        ora_err_number$         number,
        ora_err_mesg$           varchar2(2000),
        ora_err_rowid$          rowid,
        ora_err_optyp$          varchar2(2),
        ora_err_tag$            varchar2(2000),
        n1                      varchar2(128)
)
ON COMMIT PRESERVE ROWS;