【问题标题】:Want to update and insert at the same tame, both of them not only one想同时更新和插入,两者不只一个
【发布时间】:2020-03-02 11:13:20
【问题描述】:

我有一张表,其中存储了有关国家/地区的信息,我必须将 ISO 代码从 3 个字符更改为 2 个字符的 ISO 代码。 例如我有这样的数据。

问题是,首先我想更新由 3 位数字组成的所有这些设置 valid_until = '31.12.2019' 并插入应该看起来像的新行

是的,我知道有合并,但我需要更新和插入,而不是一个。

【问题讨论】:

  • 为什么不能只写两条语句并按顺序运行它们呢?目前还不清楚你的问题是什么;对于一组一致的小部分国家/地区,显示您的起始数据和所需的完成数据可能会有所帮助 - 请使用格式化文本,而不是图像。
  • 我在您的示例中没有看到任何 INSERT,只有 UPDATE
  • 完成后是否要同时拥有 AD 和 AND 行?
  • @jarlh,是的,我想保留两者,只需设置一个有效,另一个无效。

标签: sql oracle sql-merge


【解决方案1】:

假设您有另一个代码来源,这只是一个插入/更新:

update t
    set valid_until = date '2019-12-31'
    where length(iso_code) = 3;

insert into t (iso_code, valid_from, valid_to)
    select cs.iso_code_3, date '1940-01-01', date '3199-12-31'
    from t join
         codesource cs
         on t.iso_code = cs.iso_code_2;

如果您希望它们“同时”生效,您可以将其包装到单个事务中。

【讨论】:

  • 是的,类似这样,更新对所有相同的都是正确的,但是我怎样才能为所有国家/地区执行插入语句,我的意思是它应该是自动的,如果可能的话
【解决方案2】:

同意 Alex 和 Gordon 的观点,这可以作为包装在单个事务中的 2 个语句运行。因此,并不清楚为什么这需要是单个 SQL 语句。我尝试在merge 的using 子句中使用重复的行来使更新和插入一起发生(参见下面的sn-p)。请检查这是否是您想要实现的目标。

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  |

【讨论】:

    猜你喜欢
    • 2014-07-16
    • 1970-01-01
    • 1970-01-01
    • 2010-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-18
    相关资源
    最近更新 更多