Src
**************************
EMPID ENTERTAINMENT
**************************
101 BaseBall,Cricket
102 Badminton,Chess
103 Golf,Reading Books
************************************
使用定界符,
拆分记录并将其添加到目标表中。
Tgt
**************************
EMP_ID ENTERTAINMENT
**************************
101 BaseBall
101 Cricket
102 Badminton
102 Chess
103 Golf
103 Reading Books
**********************************
删除从源表到目标表不匹配的行。即如果源表中发生任何更改,也需要在目标表中复制相同的内容。
预期方案示例:
Src
**************************
EMPID ENTERTAINMENT
**************************
101 BaseBall
102 Badminton
103 Golf,Reading Books
************************************
Tgt
**************************
EMP_ID ENTERTAINMENT
**************************
101 BaseBall
102 Badminton
103 Golf
103 Reading Books
**********************************
由于源表(Src)表中没有可用数据,因此我已从target(Tgt)表中删除了101即(101-板球)和102即即(102-国际象棋)。 谁能建议,如何使用SQL查询来实现?
答案 0 :(得分:1)
首先,为SRC测试数据:
create table src(empid, ENTERTAINMENT) as
select 101, 'BaseBall,Cricket' from dual union all
select 102, 'Badminton,Chess' from dual union all
select 103, 'Golf,Reading Books' from dual;
现在创建一个与TGT应该对应的视图:
create or replace view v_tgt as
select empid, x.entertainment
from src, xmltable(
'if (contains($X,",")) then ora:tokenize($X,",") else $X'
passing entertainment as X
columns entertainment varchar2(64) path '.'
) x;
这是分割字符串的许多方法之一。其他一些内容请参见https://stewashton.wordpress.com/category/splitting-strings/。
现在从视图中创建TGT表:
create table tgt as select * from v_tgt;
最后,这是一条MERGE语句,它将把TGT与V_TGT进行比较,并使TGT相同:
merge /*+ qb_name(SYNC_PARTITION) USE_NL(O) */ into (
select /*+ qb_name(target) */
"EMPID", "ENTERTAINMENT", rowid Z##RID
from TGT
) O
using (
select /*+ qb_name(CDC_PARTITION) */ * from (
select /*+ qb_name(before_filter) */
"EMPID", "ENTERTAINMENT",
case
when Z##NEW = 1
and sum(Z##NEW) over(partition by
"EMPID", "ENTERTAINMENT"
order by null rows unbounded preceding) > sum(Z##OLD) over(partition by
"EMPID", "ENTERTAINMENT"
)
then 'I'
when Z##OLD = 1
and sum(Z##OLD) over(partition by
"EMPID", "ENTERTAINMENT"
order by null rows unbounded preceding) > sum(Z##NEW) over(partition by
"EMPID", "ENTERTAINMENT"
)
then 'D'
end Z##OP, Z##RID
FROM (
select /*+ qb_name(old) */
"EMPID", "ENTERTAINMENT",
1 Z##OLD, 0 Z##NEW, rowid Z##RID
from TGT O
union all
select /*+ qb_name(new) */
"EMPID", "ENTERTAINMENT",
0, 1, null
from v_tgt N
)
)
where Z##OP is not null
) N
on (
O.Z##RID = n.Z##RID
)
when matched then update set
"EMPID"=N."EMPID"
delete where N.Z##OP = 'D'
when not matched then insert (
"EMPID", "ENTERTAINMENT"
) values(
N."EMPID", N."ENTERTAINMENT"
);
我使用以下工具生成了此MERGE语句:https://stewashton.wordpress.com/2018/02/12/comp_sync-1-a-new-table-compare-sync-package/
最好的问候, 炖阿什顿