针对Oracle数据库批处理"更新与插入"查询

jwa*_*jwa 1 java database oracle jdbc

假设我有一个Oracle数据库,其中有一个表,RUN_LOG我正在使用它来记录作业执行的时间.

该表具有JOB_NAME唯一标识已执行作业的主键,以及一个LAST_RUN_TIMESTAMP在上次执行作业时反映的列.

作业启动时,我想更新作业的现有行(如果存在),或者在表中插入新行.

鉴于Oracle不支持a- REPLACE INTOstyle查询,有必要尝试一个UPDATE,如果零行受到影响,请使用INSERT.

这通常通过jdbc使用以下内容实现:

PreparedStatement updateStatement = connection.prepareStatement("UPDATE ...");
PreparedStatement insertStatement = connection.prepareStatement("INSERT ...");

updateStatement.setString(1, "JobName");
updateStatement.setTimestamp(2, timestamp);

// If there are no rows to update, it must be a new job...
if (updateStatement.executeUpdate() == 0) {
    // Follow-up 
    insertStatement.setString(1, "JobName");
    insertStatement.setTimestamp(2, timestamp);
    insertStatement.executeUpdate();
}
Run Code Online (Sandbox Code Playgroud)

这是一条相当完善的道路,我对这种方法非常满意.


但是,我们假设我的用例要求我插入大量的这些记录.对数据库执行单独的SQL查询将太"唠叨".相反,我想开始批处理这些INSERT/ UPDATE查询

鉴于UPDATE查询的执行将被推迟到批处理提交之前,我无法观察到在以后的日期有多少行受到影响.

实现这种REPLACE INTO结果的最佳机制是什么?

我宁愿避免使用存储过程,因为我更喜欢将持久性逻辑保留在这个地方(类),而不是在Java代码和数据库之间分配.

小智 5

SQL MERGE语句怎么样?您可以将大量记录插入临时表,然后将临时表与RUN_LOG合并例如:

merge into RUN_LOG tgt using (
   select job_name, timestamp 
   from my_new_temp_table 
) src 
on (src.job_name = tgt.job_name) 
when matched then update set
   tgt.timestamp = src.timestamp
when not matched then insert values (src.job_name, src.timestamp)
;
Run Code Online (Sandbox Code Playgroud)