【问题标题】:Oracle multi-row 'insert if not exists' from select joined with table literalOracle 多行“如果不存在则插入”选择与表文字连接
【发布时间】:2017-03-14 12:47:30
【问题描述】:

假设我有以下表结构:

a (a_id number primary key, a_code varchar unique not null)
b (b_id number primary key, a_id number foreign key references a(a_id), b_value varchar

我需要在表b 上插入几百对(a_id, b_value)(如果它们尚不存在),并且我拥有的信息是(a_code, b_value)。我来自 Postgres 背景,这样做是微不足道的,但我很难找到一种在 Oracle 中实现它的方法,而无需求助于创建并随后删除物化视图,或每行插入一次。

这是我能想到的最不难看的解决方案:

insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(b_value, iun_b_value) */
into b (b_id, a_id, b_value)
select b_id.nextval, a_id, b_value
from a
inner join

(select 'code1' a_code, 'value1' b_value from dual union all
select 'code2' a_code, 'value2' b_value from dual union all
select 'code3' a_code, 'value3' b_value from dual union all
select 'code4' a_code, 'value4' b_value from dual) new

on a.a_code = new.b_value

但我被告知我不能使用该语义提示来处理生产中的重复行,所以我尝试了这个:

merge into b using
  (select a_id, b_value
  from a inner join 

  (select 'code1' a_code, 'value1' b_value from dual union all
  select 'code2' a_code, 'value2' b_value from dual union all
  select 'code3' a_code, 'value3' b_value from dual union all
  select 'code4' a_code, 'value4' b_value from dual) new

  new on a.a_code = new.a_code) insert_codes

on (insert_codes.a_code = b.a_code and insert_codes.b_value = b.b_value)
when not matched then
  insert (b.b_id, b.a_id, b.b_value)
  values (b_id.nextval, insert_codes.a_id, 1, insert_codes.b_value)

但是当我尝试使用where not exists 子句解决此问题时,我在子选择中引用别名时遇到了相同的"ORA-00980: synonym translation is no longer valid" 错误。

有没有什么方法可以在没有物化视图或多次插入的情况下做到这一点?

【问题讨论】:

    标签: sql oracle insert multirow


    【解决方案1】:

    查看我的简化示例让我意识到出了什么问题。 on 子句是

    on (insert_codes.a_code = b.a_code and insert_codes.b_value = b.b_value)
    

    但应该是的

    on (insert_codes.a_id = b.a_id and insert_codes.b_value = b.b_value)
    

    所以这行得通:

    merge into b using
      (select a_id, b_value
      from a inner join 
    
      (select 'code1' a_code, 'value1' b_value from dual union all
      select 'code2' a_code, 'value2' b_value from dual union all
      select 'code3' a_code, 'value3' b_value from dual union all
      select 'code4' a_code, 'value4' b_value from dual) new
    
      new on a.a_code = new.a_code) insert_codes
    
    on (insert_codes.a_id = b.a_id and insert_codes.b_value = b.b_value)
    when not matched then
      insert (b.b_id, b.a_id, b.b_value)
      values (b_id.nextval, insert_codes.a_id, 1, insert_codes.b_value)
    

    在这里发帖以防其他人将来无法完成相同类型的插入。

    【讨论】:

    • 这个问题没有意义。该解决方案非常有意义,但与您的问题不一致。在您所说的问题中,您拥有的信息是(a_code, b_value)。这没有意义,因为它没有告诉您应该附加到哪个a_id。然而,在解决方案中,在“更正”的on 子句中,您使用insert_codes.a_id。那么,您实际上有 (a_id, b_value) 而不是 (a_code, b_value) 作为输入吗?这将回答所有问题。事实上,你对错误的问题给出了正确的解决方案。
    • 我忘了提到a_ida_code 之间存在一对一的关系,我的错(我将编辑问题以反映这一点)。 a_code 也是唯一的,不为空,只是不是主键。我的文字,别名为new (a_code, b_value) 对。我将它与表 a 连接起来,以便为每个 a_code 文字获取相应的 a_id,从而获得我想要插入的 (a_id, b_value) 对,并将 that 别名为 @ 987654340@。所以合并的on 子句失败了,因为我引用了一个没有意义的字段,甚至在insert_codes 中都不存在。
    猜你喜欢
    • 2020-02-04
    • 2015-07-18
    • 1970-01-01
    • 2010-12-14
    • 1970-01-01
    • 2014-03-31
    • 2012-06-01
    • 2012-12-17
    • 2012-03-14
    相关资源
    最近更新 更多