我正在使用mybatis在oracle DB上执行大量批量插入。
我的过程非常简单:我从文件列表中获取记录,并在对数据执行某些检查后将它们插入到特定的表中。
- 每个文件平均包含180.000条记录,我可以拥有多个文件。
- 某些记录可以出现在多个文件中。
- 如果每列匹配,则记录与另一个记录相同,换句话说,我不能简单地对特定字段执行检查。我已在我的数据库中定义了一个约束,以确保满足此条件。
简单地说,我想忽略Oracle在违反约束的情况下会给我的约束异常。
记录不存在? - >插入
记录已存在? - >继续
这可能是mybatis吗?或者我可以在DB级别完成某些事情吗?
我可以控制Application Server和DB,所以请告诉我完成此任务的最有效方法是什么(即使我希望避免过多依赖DB ...)< / p>
当然,我希望在每次插入之前避免执行select * ...考虑到我处理的记录数量会破坏我的应用程序的性能
答案 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;