来自 select 的 Oracle 多行 'insert if not exists' 与 table 文字结合
Oracle multi-row 'insert if not exists' from select joined with table literal
假设我有以下 table 结构:
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
我需要在 table 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"
错误。
有没有不用物化视图或多次插入的方法?
查看我的简化示例让我意识到出了什么问题。 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)
在此处发帖,以防其他人将来在插入相同类型的内容时遇到问题。
假设我有以下 table 结构:
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
我需要在 table 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"
错误。
有没有不用物化视图或多次插入的方法?
查看我的简化示例让我意识到出了什么问题。 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)
在此处发帖,以防其他人将来在插入相同类型的内容时遇到问题。