批量插入:有没有办法在违反约束时跳过下一条记录?
Batch insert: is there a way to just skip on next record when a constraint is violated?
我正在使用 mybatis 在 oracle 数据库上执行大量批量插入。
我的过程非常简单:我从文件列表中获取记录,并在对数据执行一些检查后将它们插入特定的 table。
-每个文件平均包含 180.000 条记录,我可以有多个文件。
-有些记录可以出现在多个文件中。
-如果每个列都匹配,则一条记录与另一条记录相同,换句话说,我不能简单地对特定字段执行检查。我在我的数据库中定义了一个约束,以确保满足此条件。
简而言之,我只想忽略 Oracle 在违反约束的情况下给我的约束异常。
记录不存在?-->插入
记录已经存在?--> 继续
这可以用 mybatis 实现吗?或者我可以在数据库级别完成一些事情吗?
我可以控制应用程序服务器和数据库,所以请告诉我完成此任务的最有效方法是什么(即使我想避免过多地依赖数据库...)
当然,我想避免在每次插入之前执行 select*...鉴于我正在处理的记录数量会破坏我的应用程序的性能
我不确定 JDBC,但至少在 OCI 中是可能的。通过批处理操作,您可以将向量作为绑定变量传递,还可以返回返回 ID 的向量以及错误代码的向量。
您还可以在数据库服务器端将 MERGE 与自定义集合类型一起使用。类似于:
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"
是一个用于从绑定变量转换为 table.
的结构
另一种选择是使用SQL错误登录子句:
DBMS_ERRLOG.create_error_log (dml_table_name => 't');
insert into t(...) values(...) log errors reject limit unlimited;
然后在加载后你将不得不截断错误记录 table err$_t;
- 另一种选择是使用 external tables
与使用 sqlldr 相比,看起来任何解决方案都需要做很多工作。
使用IGNORE_ROW_ON_DUPKEY_INDEX提示:
insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(table_name index_name) */
into table_name
select * ...
忽略有错误的错误table
insert
into table_name
select *
from selected_table
LOG ERRORS INTO SANJI.ERROR_LOG('some comment' )
REJECT LIMIT UNLIMITED;
错误table 模式是:
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;
我正在使用 mybatis 在 oracle 数据库上执行大量批量插入。
我的过程非常简单:我从文件列表中获取记录,并在对数据执行一些检查后将它们插入特定的 table。
-每个文件平均包含 180.000 条记录,我可以有多个文件。
-有些记录可以出现在多个文件中。
-如果每个列都匹配,则一条记录与另一条记录相同,换句话说,我不能简单地对特定字段执行检查。我在我的数据库中定义了一个约束,以确保满足此条件。
简而言之,我只想忽略 Oracle 在违反约束的情况下给我的约束异常。
记录不存在?-->插入
记录已经存在?--> 继续
这可以用 mybatis 实现吗?或者我可以在数据库级别完成一些事情吗?
我可以控制应用程序服务器和数据库,所以请告诉我完成此任务的最有效方法是什么(即使我想避免过多地依赖数据库...)
当然,我想避免在每次插入之前执行 select*...鉴于我正在处理的记录数量会破坏我的应用程序的性能
我不确定 JDBC,但至少在 OCI 中是可能的。通过批处理操作,您可以将向量作为绑定变量传递,还可以返回返回 ID 的向量以及错误代码的向量。
您还可以在数据库服务器端将 MERGE 与自定义集合类型一起使用。类似于:
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"
是一个用于从绑定变量转换为 table.
另一种选择是使用SQL错误登录子句:
DBMS_ERRLOG.create_error_log (dml_table_name => 't');
insert into t(...) values(...) log errors reject limit unlimited;
然后在加载后你将不得不截断错误记录 table err$_t;
- 另一种选择是使用 external tables
与使用 sqlldr 相比,看起来任何解决方案都需要做很多工作。
使用IGNORE_ROW_ON_DUPKEY_INDEX提示:
insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(table_name index_name) */
into table_name
select * ...
忽略有错误的错误table
insert
into table_name
select *
from selected_table
LOG ERRORS INTO SANJI.ERROR_LOG('some comment' )
REJECT LIMIT UNLIMITED;
错误table 模式是:
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;