使用其他表的值更新表

时间:2018-11-14 14:59:47

标签: sql oracle oracle11g

我要清理我的桌子:

rid(PK)     rval
----------- ----------
10          test
11          Rtest
12          dummy
13          test
14          Rtest

要从列rval中删除重复的值,所以我最终得到:

rid(PK)     rval
----------- ----------
10          test
11          Rtest
12          dummy

但是我还有另一个具有外键关系的表,该表使用我要删除的值:

ruid       rid(FK)
---------- ----------
1          10
2          10
3          12
4          13
5          13
6          14
7          14

因此,在删除之前,我需要更新该表以使用我保留的匹配rid,例如更新14至11;这样该表将最终显示为:

ruid       rid(FK)
---------- ----------
1          10
2          10
3          12
4          10
5          10
6          11
7          11

我该怎么做?

1 个答案:

答案 0 :(得分:1)

您可以使用分析汇总为每个rid获得最低的rval

min(rid) over (partition by rval)

,并在连接两个表的子查询中使用它(我没有想象出它们的真实名称,我曾想象它们称为t1t2),因此您可以看到最合适的{每个rid的{​​1}}:

ruid

然后可以在合并语句中使用它:

select t2.ruid, t2.rid, x.min_rid
from (
  select rid, min(rid) over (partition by rval) as min_rid from t1
) x
join t2 on t2.rid = x.rid;

      RUID        RID    MIN_RID
---------- ---------- ----------
         1         10         10
         2         10         10
         3         12         12
         4         13         10
         5         13         10
         6         14         11
         7         14         11

完成后,您可以删除冗余PK值:

merge into t2
using (
  select t2.ruid, t2.rid, x.min_rid
  from (
    select rid, min(rid) over (partition by rval) as min_rid from t1
  ) x
  join t2 on t2.rid = x.rid
) y
on (t2.ruid = y.ruid)
when matched then update set t2.rid = y.min_rid
where t2.rid != y.min_rid;

4 rows merged.

select * from t2;

      RUID        RID
---------- ----------
         1         10
         2         10
         3         12
         4         10
         5         10
         6         11
         7         11

Id delete from t1 where exists (select * from t1 x where x.rval = t1.rval and x.rid < t1.rid); 2 rows deleted. select * from t1; RID RVAL ---------- ----- 10 test 11 Rtest 12 dummy 不是唯一的,并且没有其他唯一键可以包含在语句中,因此您不能真正使用合并-您不能在引用中引用ruid rid子句,因为这是您要更新的列。

您可以改为进行相关更新:

on

这将更新每一行;如果您有大量数据和/或需要更改的比例很小,则可以添加过滤器以仅更新那些数据:

update t2
set rid = (
  select min_rid
  from (
    select rid, min(rid) over (partition by rval) as min_rid from t1
  ) x
  where x.rid = t2.rid
);