前言
在知识局限的我们,有时候,方法的高效性,真的很重要。
问题
项目中有个表的数据要从另一个数据库中同步,同步的机制为,若表中的某条数据某个字段更新了,则更新此字段,若干字段更新,则更新若干字段,对表没更新的字段,则略过…
分析
假设本地表为A,远程表为B,从需要从B同步更新的数据到A,正常操作流程为:
- 判断数据字段是否有更新
- 忽略掉那些没更新的记录(因为待同步的表数据量很大,全表更新慢…)
- 从代码层,对比一个有N条数据M个字段的表的操作
方案1
原本的做法是定义2个对象,一个查询远程表所有记录,一个查询本地表所有记录,然后同步一个字段一个字段的判断是否相同,从而判断是否更新本地记录。
例如
Table tableA;
Tabel tableB;
List<tableA> tableAList = tableADAO.findAll();//取出远程记录
List<tableB> tableBList = tableBDAO.findAll();//取出本地记录
for(Table a : tableAList){
for(Tabel b: tableBList){
if(b.getX1() == a.getX1()){
//则更新
}
if(b.getX2() == a.getX2()){
//则更新
}
.......
}
}
说明
这方案就是个巨坑……
方案2
数据源在远程服务器端,因此,本地的数据是可以进行增删改查而不会影响系统的正常运行,所以,进行同步时,最简便的方法为:
先删除本地记录,再把远程表对应的数据insert
进本地表里。“先delete
,再insert
”
说明
这方案,在允许删除数据的前提下,操作简便快捷,推荐。
方案3
方案2的可行性还是值得推荐的,但是,有一定的前提,而且,写起代码来,也有一定的代码量,有无更简便的方法呢,例如一行代码就解决的?脑中出现这个疑惑(没办法,谁叫我懒),经查询,发现了个Oracle9i
以上都支持的sql方法merge into
。(现在想想,我们现在能想到的问题,别人,特别是大公司,也肯定能想到做到)。于是乎,普及了下merge into
的使用,豁然开朗,还真能解决我一行代码搞定的事:
merge into 是oracle9i新增的语法,用来合并
update
和insert
语句。通过merge
语句,根据一张表或者子查询的连接条件对另一个表进行查询,连接条件匹配上的进行update
,无法匹配的进行insert
。这个语法仅需要完成一次全表扫描就完成了全部工作,执行效率高于insert+ update
。
语法:
merge [into [schema .] table [t_alias]
using [schema .] {table | view | subquery} [t_alias]
on (condition)
when matched then merge_update_clause
when not matched then merge_insert_clause;
有了此方法,我写好sql
,通过DAO
调用,瞬间完成同步功能。吊炸天了。又一次被我偷懒感动了。
下面是我的一个例子:
-- create table
create table merc_termconvert
{
slt_termcode char(8) not null, --1
slt_merccode char(15) not null, --2
merctype char(2) not null, --3
ispcode char(3) default 000 not null, --4
termcode char(8) not null,
--todo
}
其中1,2,3,4
为联合主键(这点很重要,因为主键的值是不能更新的,所以再merge into
的语句里,是不能出现在when matched then
后的update
语句中的。
merge into merc_termconvert2 t2
using merc_termconvert t
on( t2.slt_termcode = t.slt_termcode and t2.slt_merccode = t.slt_merccode and t2.merctype = t.merctype and t2.ispcode = t.ispcode) --1
when not matched then --2
insert(xxx,xxx,xxx,xxx,xxx) values(yyy, yyy, yyy, yyy...)
when matched then --3
update
set t2.termcode = t.termcode,
xxx = yyy,
xxx = yyy,
xxx = yyy,
xxx = yyy,
-- todo
说明
是需要将merc_termconvert
的数据同步更新到 merc_termconvert2
的远程表中。
1、没有匹配到记录时,实现的insert
语句,数据的来源于本地表merc_termconvert
2、粉色箭头,指示的是这个表的4个联合主键,需要全部进行赋值在on
的语句里。
3、匹配到的记录时,实现的updat
e语句,数据来源于本地表merc_termconvert
,而且,主键是不允许设置在此出现的。
具体的做法,参考上面的代码。
完