Sql “合并时如何执行两个不同的操作”;“不匹配”;

Sql “合并时如何执行两个不同的操作”;“不匹配”;,sql,oracle,merge,Sql,Oracle,Merge,我有这两张桌子 TABLE1 nrb score note source nrb1 500 abc e1 nrb2 500 def e1 及 有三种情况下,我希望执行不同的操作。我需要用新值修改表1: 当匹配(通过NRB)(f.ex.“nrb1”)时,我希望将table1中的值保留到此NRB中,因此基本上:不处理此记录 当不匹配时#1:在表2中有nrb,但在表1中没有(例如'nrb3'),我想将此nrb的值从表2插入表1 当不匹配时#2:如果表1中存在nrb,但

我有这两张桌子

TABLE1
nrb   score  note  source
nrb1    500  abc   e1
nrb2    500  def   e1

有三种情况下,我希望执行不同的操作。我需要用新值修改表1:

  • 当匹配(通过NRB)(f.ex.“nrb1”)时,我希望将
    table1
    中的值保留到此
    NRB
    中,因此基本上:不处理此记录

  • 当不匹配时#1:在
    表2中有
    nrb
    ,但在
    表1中没有(例如
    'nrb3'
    ),我想将此
    nrb
    的值从
    表2
    插入
    表1

  • 当不匹配时#2:如果
    表1
    中存在
    nrb,但
    表2
    中没有(例如
    'nrb2'
    ),我想将
    表1
    中的
    得分
    从500改为5

  • 所以最后应该是这样的:

    TABLE1
    nrb   score  note  source
    nrb1    500  abc   e1 [stays the same]
    nrb2      5  def   e1 [score changed]
    nrb3    500  dls   e1 [new record from table2]
    

    我需要使用Oracle的
    merge
    语句来执行此任务,但我不知道如何执行两种不同的操作。

    您不能在一次合并中执行此操作。
    when not matched
    子句只能插入,不能更新,如图所示

    类似地,匹配时的
    子句只能更新,不能插入。他们之间不能混搭

    您必须有一个单独的update语句。您可以合并以执行第一部分:

    merge into table1 t1
    using (select * from table2) t2
    on (t2.nrb = t1.nrb)
    when not matched then insert (nrb, score, note, source)
      values (t2.nrb, t2.score, t2.note, t2.source);
    
    或进行等效插入:

    insert into table1 (nrb, score, note, source)
    select t2.nrb, t2.score, t2.note, t2.source
    from table2 t2
    where not exists (
      select null
      from table1 t1
      where t1.nrb = t2.nrb
    );
    
    select * from table1;
    
    NRB       SCORE NOT SO
    ---- ---------- --- --
    nrb1        500 abc e1
    nrb2        500 def e1
    nrb3        500 dls e1
    
    然后,无论您执行哪种操作,都会在不匹配的地方进行更新:

    update table1 t1
    set score = score/100 -- or fixed value 5; unclear which you need
    where not exists (
      select null
      from table2 t2
      where t2.nrb = t1.nrb
    );
    
    select * from table1;
    
    NRB       SCORE NOT SO
    ---- ---------- --- --
    nrb1        500 abc e1
    nrb2          5 def e1
    nrb3        500 dls e1
    
    如果您真的想这样做,您可以通过合并进行更新,但这会使
    using
    子句变得更复杂-表1
    的子集在
    表2
    中没有匹配记录-因此我看不到任何好处:

    merge into table1 t1
    using (
      select * from table1 t1
      where not exists (
        select null from table2 t2 where t2.nrb = t1.nrb)) t2
    on (t2.nrb = t1.nrb)
    when matched then update set t1.score = score/100;
    

    你不能在一次合并中做到这一点。
    when not matched
    子句只能插入,不能更新,如图所示

    类似地,匹配时的
    子句只能更新,不能插入。他们之间不能混搭

    您必须有一个单独的update语句。您可以合并以执行第一部分:

    merge into table1 t1
    using (select * from table2) t2
    on (t2.nrb = t1.nrb)
    when not matched then insert (nrb, score, note, source)
      values (t2.nrb, t2.score, t2.note, t2.source);
    
    或进行等效插入:

    insert into table1 (nrb, score, note, source)
    select t2.nrb, t2.score, t2.note, t2.source
    from table2 t2
    where not exists (
      select null
      from table1 t1
      where t1.nrb = t2.nrb
    );
    
    select * from table1;
    
    NRB       SCORE NOT SO
    ---- ---------- --- --
    nrb1        500 abc e1
    nrb2        500 def e1
    nrb3        500 dls e1
    
    然后,无论您执行哪种操作,都会在不匹配的地方进行更新:

    update table1 t1
    set score = score/100 -- or fixed value 5; unclear which you need
    where not exists (
      select null
      from table2 t2
      where t2.nrb = t1.nrb
    );
    
    select * from table1;
    
    NRB       SCORE NOT SO
    ---- ---------- --- --
    nrb1        500 abc e1
    nrb2          5 def e1
    nrb3        500 dls e1
    
    如果您真的想这样做,您可以通过合并进行更新,但这会使
    using
    子句变得更复杂-表1
    的子集在
    表2
    中没有匹配记录-因此我看不到任何好处:

    merge into table1 t1
    using (
      select * from table1 t1
      where not exists (
        select null from table2 t2 where t2.nrb = t1.nrb)) t2
    on (t2.nrb = t1.nrb)
    when matched then update set t1.score = score/100;
    

    您需要使用两个不同的SQL执行两个单独的任务。因为当不匹配条件时,合并不支持更新子句

    • 合并插入
    • 更新不存在的位置
    设置

    SQL> CREATE TABLE t1(
      2  nrb VARCHAR2(10), score NUMBER, note VARCHAR2(10), SOURCE VARCHAR2(10)
      3  );
    
    Table created.
    
    SQL> INSERT INTO t1 VALUES('nrb1', 500, 'abc', 'e1');
    
    1 row created.
    
    SQL> INSERT INTO t1 VALUES('nrb2', 500, 'def', 'e1');
    
    1 row created.
    
    SQL> COMMIT;
    
    Commit complete.
    
    SQL> CREATE TABLE t2(
      2  nrb VARCHAR2(10), score NUMBER, note VARCHAR2(10), SOURCE VARCHAR2(10)
      3  );
    
    Table created.
    
    SQL> INSERT INTO t2 VALUES('nrb1', 500, 'gls', 'e1');
    
    1 row created.
    
    SQL> INSERT INTO t2 VALUES('nrb3', 500, 'dls', 'e1');
    
    1 row created.
    
    SQL> COMMIT;
    
    Commit complete.
    
    合并插入:插入不匹配的行

    SQL> MERGE INTO t1
      2  USING t2
      3  ON (t1.nrb = t2.nrb)
      4  WHEN NOT MATCHED THEN
      5    INSERT
      6      (
      7        nrb,
      8        score,
      9        note,
     10        SOURCE
     11      )
     12      VALUES
     13      (
     14        t2.nrb,
     15        t2.score,
     16        t2.note,
     17        t2.SOURCE
     18      );
    
    1 row merged.
    
    SQL> COMMIT;
    
    Commit complete.
    
    SQL> SELECT * FROM t1;
    
    NRB             SCORE NOTE       SOURCE
    ---------- ---------- ---------- ----------
    nrb1              500 abc        e1
    nrb2              500 def        e1
    nrb3              500 dls        e1
    
    UPDATE语句:使用自定义值更新不匹配的行

    SQL> UPDATE t1
      2  SET    score = 5
      3  WHERE  NOT EXISTS (SELECT NULL
      4                     FROM   t2
      5                     WHERE  t1.nrb = t2.nrb);
    
    1 row updated.
    
    SQL>                    COMMIT;
    
    Commit complete.
    
    SQL> SELECT * FROM t1;
    
    NRB             SCORE NOTE       SOURCE
    ---------- ---------- ---------- ----------
    nrb1              500 abc        e1
    nrb2                5 def        e1
    nrb3              500 dls        e1
    

    注意与只使用INSERT的合并不同,您只需编写一条INSERT语句。尽管如此,从wards上的
    10g
    ,匹配子句和不匹配子句是可选的,因此您可以有单个INSERT或单个UPDATE语句。

    您需要使用两个不同的SQL执行两个单独的任务。因为当不匹配条件时,合并不支持更新子句

    • 合并插入
    • 更新不存在的位置
    设置

    SQL> CREATE TABLE t1(
      2  nrb VARCHAR2(10), score NUMBER, note VARCHAR2(10), SOURCE VARCHAR2(10)
      3  );
    
    Table created.
    
    SQL> INSERT INTO t1 VALUES('nrb1', 500, 'abc', 'e1');
    
    1 row created.
    
    SQL> INSERT INTO t1 VALUES('nrb2', 500, 'def', 'e1');
    
    1 row created.
    
    SQL> COMMIT;
    
    Commit complete.
    
    SQL> CREATE TABLE t2(
      2  nrb VARCHAR2(10), score NUMBER, note VARCHAR2(10), SOURCE VARCHAR2(10)
      3  );
    
    Table created.
    
    SQL> INSERT INTO t2 VALUES('nrb1', 500, 'gls', 'e1');
    
    1 row created.
    
    SQL> INSERT INTO t2 VALUES('nrb3', 500, 'dls', 'e1');
    
    1 row created.
    
    SQL> COMMIT;
    
    Commit complete.
    
    合并插入:插入不匹配的行

    SQL> MERGE INTO t1
      2  USING t2
      3  ON (t1.nrb = t2.nrb)
      4  WHEN NOT MATCHED THEN
      5    INSERT
      6      (
      7        nrb,
      8        score,
      9        note,
     10        SOURCE
     11      )
     12      VALUES
     13      (
     14        t2.nrb,
     15        t2.score,
     16        t2.note,
     17        t2.SOURCE
     18      );
    
    1 row merged.
    
    SQL> COMMIT;
    
    Commit complete.
    
    SQL> SELECT * FROM t1;
    
    NRB             SCORE NOTE       SOURCE
    ---------- ---------- ---------- ----------
    nrb1              500 abc        e1
    nrb2              500 def        e1
    nrb3              500 dls        e1
    
    UPDATE语句:使用自定义值更新不匹配的行

    SQL> UPDATE t1
      2  SET    score = 5
      3  WHERE  NOT EXISTS (SELECT NULL
      4                     FROM   t2
      5                     WHERE  t1.nrb = t2.nrb);
    
    1 row updated.
    
    SQL>                    COMMIT;
    
    Commit complete.
    
    SQL> SELECT * FROM t1;
    
    NRB             SCORE NOTE       SOURCE
    ---------- ---------- ---------- ----------
    nrb1              500 abc        e1
    nrb2                5 def        e1
    nrb3              500 dls        e1
    

    注意与只使用INSERT的合并不同,您只需编写一条INSERT语句。尽管在wards上的
    10g
    中,匹配和不匹配子句是可选的,因此您可以使用单INSERT或单UPDATE语句。

    值得注意的是,这将把所有不匹配的值设置为5。根据您的数据集和关于非500分数的规则(例如,如果分数为502?6000?等),如果需要,您还需要将其添加到where子句中。非常感谢。考虑到您的更新声明,有一个问题,为什么您的“不存在的地方”比简单的“不存在(选择)”更为优化?如下所示:更新tab1 set score=5,其中nrb不存在(从tab2中选择nrb);这是一个比之前链接的更好的回答。@bobdylan这里的重点是mpre关于合并行和非映射行的逻辑,OP应该能够理解范围和它的其他方面,或者要求进一步澄清。解决方案在OP在问题中发布的任何内容的范围内:-)@ŁukaszStasiak“不存在”和“不存在”之间存在巨大差异。这是一个常见问题,在谷歌中搜索差异,可能Tom Kyte在AskTom中回答得很好。值得注意的是,这会将所有不匹配的值设置为5。根据您的数据集和关于非500分数的规则(例如,如果分数为502?6000?等),如果需要,您还需要将其添加到where子句中。非常感谢。考虑到您的更新声明,有一个问题,为什么您的“不存在的地方”比简单的“不存在(选择)”更为优化?如下所示:更新tab1 set score=5,其中nrb不存在(从tab2中选择nrb);这是一个比之前链接的更好的回答。@bobdylan这里的重点是mpre关于合并行和非映射行的逻辑,OP应该能够理解范围和它的其他方面,或者要求进一步澄清。解决方案在OP在问题中发布的任何内容的范围内:-)@ŁukaszStasiak“不存在”和“不存在”之间存在巨大差异。这是一个常见问题,在谷歌搜索差异,可能是汤姆