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:
table1
中的值保留到此NRB
中,因此基本上:不处理此记录表2中有nrb
,但在表1中没有(例如'nrb3'
),我想将此nrb
的值从表2
插入表1
表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“不存在”和“不存在”之间存在巨大差异。这是一个常见问题,在谷歌搜索差异,可能是汤姆