Согласитесь с Алексом и Гордоном, что это можно запустить как 2 оператора, заключенные в одну транзакцию. Итак, не совсем понятно, почему это должен быть один оператор SQL. Я попытался использовать повторяющиеся строки в предложении using
в merge
, чтобы обновление и вставка происходили вместе (см. Фрагмент ниже). Пожалуйста, проверьте, хотите ли вы этого достичь.
SQLFiddle здесь
SQL> create table foo
2 as
3 select 'AD' iso_code,
4 date '2020-01-01' valid_from,
5 date '3999-12-31' valid_until
6 from dual;
SQL> select * from foo;
| ISO_CODE | VALID_FROM | VALID_UNTIL |
| AD | 1/1/2020 | 12/31/3999 |
SQL> alter table foo modify iso_code varchar2(3);
SQL> create table iso_code_mapping
2 as
3 select 'AD' iso2_code, 'AND' iso3_code from dual;
SQL> select * from iso_code_mapping;
| ISO2_CODE | ISO3_CODE |
| AD | AND |
SQL> merge into foo
2 using (
3 select iso_code, iso3_code, valid_from, valid_until from foo f
4 join iso_code_mapping i on i.iso2_code = f.iso_code
5 union all
6 select iso_code||'_2' iso_code, iso3_code, valid_from, valid_until from foo f
7 join iso_code_mapping i on i.iso2_code = f.iso_code
8 where not exists ( select 1 from foo f2 where f2.iso_code = i.iso3_code and f2.valid_until = '31 DEC 3999' )
9 ) x
10 on ( x.iso_code = foo.iso_code )
11 when matched then
12 update set valid_until = '31 DEC 2019'
13 where valid_until <> '31 DEC 2019'
14 when not matched then
15 insert (iso_code, valid_from, valid_until)
16 values (iso3_code, '1 JAN 1940', '31 DEC 3999')
17 ;
SQL> select * from foo;
| ISO_CODE | VALID_FROM | VALID_UNTIL |
| AD | 1/1/2020 | 12/31/2019 |
| AND | 1/1/1940 | 12/31/3999 |