从另一个表中删除不匹配的行

时间:2019-09-10 00:35:20

标签: sql oracle split

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查询来实现?

1 个答案:

答案 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/

最好的问候, 炖阿什顿