【问题标题】:Update between tables表之间的更新
【发布时间】:2017-07-24 10:31:36
【问题描述】:

我有两个表(ORACLE11):

TABLE1: (ID_T1 is TABLE1 primary key)
| ID_T1 | NAME  | DATEBEGIN  | DATEEND    |
| 10    | test  | 01/01/2017 | 01/06/2017 |
| 11    | test  | 01/01/2017 | null       |
| 12    | test1 | 01/01/2017 | 01/06/2017 |
| 13    | test1 | 01/01/2017 | null       |
TABLE2: (ID_T2 is TABLE2 primary key and ID_T1 is TABLE2 foreign key on TABLE1)
| ID_T2 | ID_T1 |
| 1     | 10    |
| 2     | 11    |
| 3     | 11    |
| 4     | 12    |
| 5     | 13    |

我需要从 TABLE1 中删除所有行,其中 TABLE1.DATEEND = 'null'

但首先我必须更新 TABLE2 以将 TABLE2.ID_T1 修改为 TABLE1 中相同名称的剩余记录:

TABLE2:
| ID_T2 | ID_T1 |
| 1     | 10    |
| 2     | 10    |
| 3     | 10    |
| 4     | 12    |
| 5     | 12    |

我试过了:

更新表2 设置表 2.ID_T1 = ( 选择表 1.ID_T1 从表 1 其中 TABLE1.DATEBEGIN = '01/01/2017' 并且 TABLE1.DATEEND 不为空 ) 表 2.ID_T1 = ( 选择表 1.ID_T1 从表 1 其中 TABLE1.DATEBEGIN = '01/01/2017' 并且 TABLE1.DATEEND 为 NULL ); 但我不知道如何加入 TABLE1.NAME 并为 TABLE2 的所有行执行此操作。在此先感谢您的帮助。

【问题讨论】:

  • 那么重新分配TABLE2.ID_T1 的规则是什么? TABLE1.ID_T1 的最高值是否低于TABLE2.ID_T1 的当前值,其中TABLE1.DATEEND 不为空?
  • 或者您是否保证TABLE1NAME 中始终只有一条记录,其中DATEEND 不为空?
  • 是的,我忘了提到每个 NAME 只有一条记录,其中 DATEEND 不为空
  • Oracle(在许多情况下)是一个多用户环境。您可能必须在操作期间锁定两个表。想象一下:您更新了表 2 中的 ID,其他人为表 1 中的名称添加了一个新行,并将该名称最近一行的日期更改为 NULL。然后您删除表 1 中所有日期为 NULL 的行 - 包括您认为不会被删除的行。现在您失去了表之间的连接。所以你必须确保这不会发生。

标签: oracle sql-update


【解决方案1】:

首先创建一个临时表,找出要为哪个名称保留哪个 id。在有多个可能值的情况下,我按升序或 id_t1 选择了一个。

create table table_2_update as 
select id_t1, name from (select id_t1, name row_number() over(partition by 
name order by id_t1) from table1 where name is not null) where rn=1;

创建下一张表,知道table2的哪个id连接到table1的哪个名字。

create table which_to_what as 
select t2.id_t2, t2.id_t1, t1.name from table1 t1 inner join table2 t2 on 
t1.id_t1 = t2.id_t2 group by t2.id_t2, t2.id_t1, t1.name;

由于这个新创建的表现在包含 table1 的 id 和 name,以及 table2 的 id,因此合并到其中以保留 table1 的 id 和 name 的一对一大小写。

merge into which_to_what a
using table_2_update b
on (a.name=b.name)
when matched then update set 
a.id_t1=b.id_t1;

现在我们终于有了一个包含最终正确值的表,您可以将这个故事重命名为 table2 或根据新表和原始 table2 的 id 合并原始 table2。

merge into table2 a
using which_to_what a
on (a.id_t2=b.id_t2)
when matched then update set
a.id_t1=b.id_t1;

最后从table1中删除空值。

delete from table1 where dateend is null;

【讨论】:

    【解决方案2】:

    您可以通过将table1 加入自身,加入name 列来执行此操作。使用第一个表 (a) 链接到 table2.id_t1,使用第二个表 (b) 获取 t1_id,其中 dateend 不为空。

    UPDATE table2
    SET table2.id_t1 = (
        select b.id_t1
        from   table1 a, table1 b
        where  a.name = b.name
        and    b.dateend is not null
        and    a.id_t1 = table2.id_t1
    )
    WHERE EXISTS (
        select b.id_t1
        from   table1 a, table1 b
        where  a.name = b.name
        and    b.dateend is not null
        and    a.id_t1 = table2.id_t1
    );
    

    这假设只有一个table1 记录,其中dateend 不为空。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多