我有一个Spring Batch程序,该程序从一个数据库读取数据,然后处理数据,然后写入Oracle数据库。该批处理程序每天按计划运行一次。如何避免每次运行时都添加相同的记录,而只添加源数据库中的新值?
答案 0 :(得分:1)
一种选择是创建唯一索引(或主键,如果可能的话(取决于您是否允许空值)),这将导致Oracle自动拒绝列违反唯一性的所有行。
其他选项需要一些编程。
[编辑:“悄悄地”跳过错误]
这就是我的意思:
for cur_r in (select col1, col2
from another_table@db_link)
loop
begin --> you need inner BEGIN-EXCEPTION-END block
insert into new_table (col1, col2)
values (cur_r.col1, cur_r.col2);
exception
when dup_val_on_index then
null;
end;
end loop;
另一个选项使用纯SQL(即没有PL / SQL的循环):
insert into new_table (col1, col2)
select col1, col2
from another_table@db_link
where (col1, col2) not in (select col1, col2
from new_table);
此选项甚至不需要唯一索引(尽管这不会造成损害),因为NOT IN
不会插入其列值已存在于目标表中的行。
答案 1 :(得分:1)
听起来您担心不多次处理同一张源记录。如果是这种情况,您可以在源表上添加一个字段,指示已提取数据。
哦,-在表上放一个唯一的主键。他们全部。甚至那些您认为不需要的地方。今天添加的主键是您以后不会说的“该死。我希望该表具有主键”。 Don't ask me how I know...
好运。
答案 2 :(得分:0)
我猜您正在使用RepositoryItemReader作为源。在这种情况下,可以使用@Query在源存储库中添加一个自定义方法,包括一个验证条件以避免已处理的记录,然后在RepositoryItemReader中使用该方法。
那会是
@Query("SELECT r FROM Records r WHERE r.isNew = 1")
Collection<Record> findAllNewRecords();
然后像这样配置阅读器
RepositoryItemReader<Record> recordsReader = new RepositoryItemReader<>();
recordsReader.setRepository(recordsRepository);
recordsReader.setMethodName("findAllNewRecords");
希望有帮助
答案 3 :(得分:0)
create table T_UNIQUE_VALUE( a number,b number, c varchar2(100));
alter table T_UNIQUE_VALUE ADD CONSTRAINT C_UNIQUE_VALUE UNIQUE (a,b);
定义日志错误表。 Oralce将创建err$_table_name
BEGIN
DBMS_ERRLOG.create_error_log(dml_table_name => 'T_UNIQUE_VALUE');
END;
测试一下。
execut 2 times
insert into T_UNIQUE_VALUE values(1,1,'a') LOG ERRORS REJECT LIMIT UNLIMITED;
--check table T_UNIQUE_VALUE and err$_T_UNIQUE_VALUE
select * from err$_T_UNIQUE_VALUE; -- 1 row
select * from T_UNIQUE_VALUE; -- 1 row
修改弹簧注释。
@Modifying
@Query(value = "insert into T_UNIQUE_VALUE values(:a,:b,:c) LOG ERRORS REJECT LIMIT UNLIMITED", nativeQuery = true)
void insert_balbla(...)