【问题标题】:How to update a column in an Oracle table from another table如何从另一个表更新 Oracle 表中的列
【发布时间】:2021-01-22 10:23:41
【问题描述】:

我有一个名为 PENSION 的表,其中包含以下数据

PERSNO MMYY AMT   STNO
C01234 0120 1000  null
C01234 0220 1100  null
C01234 0320 1050  null
C02563 0120 1000  null
C02563 0220 950   null
C02563 0320 1200  null

我还有另一个表 EMPLOYEE,其中包含以下数据

PERSNO STNO
C01234 1521
C02563 2365
C01891 2593

每当 PENSION 表的 PERSNO 字段与 EMPLOYEE 表匹配时,我需要用 EMPLOYEE 表的 STNO 字段的值更新 PENSION 表的 STNO 字段。

有人可以建议我在 Oracle 中执行此操作的 SQL 查询吗?

【问题讨论】:

    标签: sql oracle


    【解决方案1】:

    一个不错的MERGE 选项:

    merge into pension p
    using employee e
    on (p.persno = e.persno)
    when matched then 
    update set p.stno = e.stno;
    

    使用您发布的示例数据(稍作修改;不想输入那么多):

    SQL> select * From pension;
    
    PERSNO       STNO        AMT
    ------ ---------- ----------
    c01234                     1
    c01234                     3
    c01234                     5
    c02563                     2
    c02563                     9
    c02563                     2
    
    6 rows selected.
    
    SQL> select * From employee;
    
    PERSNO       STNO
    ------ ----------
    c01234       1521
    c02563       2365
    c01891       2593
    
    SQL> merge into pension p
      2  using employee e
      3  on (p.persno = e.persno)
      4  when matched then
      5  update set p.stno = e.stno;
    
    6 rows merged.
    
    SQL> select * from pension;
    
    PERSNO       STNO        AMT
    ------ ---------- ----------
    c01234       1521          1
    c01234       1521          3
    c01234       1521          5
    c02563       2365          2
    c02563       2365          9
    c02563       2365          2
    
    6 rows selected.
    
    SQL>
    

    但是,如果EMPLOYEE 表中有重复的PERSNO:

    SQL> select * from employee order by persno;
    
    PERSNO       STNO
    ------ ----------
    c01234       1521      --> two rows for 
    c01234       9999      --> c01234
    c01891       2593
    c02563       2365
    

    查询不再起作用,因为它无法决定使用这两行中的哪一行。 你知道吗?如果是这样,请告诉我们。或者,如果不允许重复,请将其删除,merge 将再次起作用。

    SQL> merge into pension p
      2  using employee e
      3  on (p.persno = e.persno)
      4  when matched then
      5  update set p.stno = e.stno;
    merge into pension p
               *
    ERROR at line 1:
    ORA-30926: unable to get a stable set of rows in the source tables
    
    
    SQL>
    

    如果您决定选择例如MIN(EMPLOYEE.STNO) 值,那么您将查询重写为

    SQL> merge into pension p
      2  using (select e.persno, min(e.stno) stno
      3         from employee e
      4         group by e.persno
      5        ) x
      6  on (p.persno = x.persno)
      7  when matched then
      8  update set p.stno = x.stno;
    
    6 rows merged.
    
    SQL>
    

    它会再次工作。

    【讨论】:

    • 它给出了错误:错误报告:SQL 错误:ORA-30926:无法在源表中获得稳定的行集 30926.00000 -“无法在源表中获得稳定的行集源表” *原因:由于大量 dml 活动或不确定的 where 子句,无法获得一组稳定的行。 *行动:删除任何非确定性 where 子句并重新发布 dml。
    • 这意味着您在 EMPLOYEE 表中有重复项(每个 PERSNO)。这是允许的吗?如果是这样,您要使用哪一行?因为,根据您发布的示例数据,它工作 OK。请参阅编辑后的答案。
    • 如何正确查询,以防员工表中存在重复条目。
    • 你必须以某种方式摆脱它们。要么删除它们,要么重写 MERGE,以便每个员工使用一个 STNO - 例如,MIN(STNO)。我编辑了答案并将该示例添加到最后,看看。
    猜你喜欢
    • 2023-03-08
    • 2018-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多