假设我有一个包含两列的数据库表 - 车辆和位置。
每辆车都有很多地方。
当我的程序收到包含每辆车的位置列表的消息时,我可以做任何……
假设你有车辆 V1 有地点 A , B 和 X 和车辆 V2 有地点 B 和 Q 。该消息是针对车辆的 V1 有地点 A , Y 。
V1
A
B
X
V2
Q
Y
对于 delete 您可以使用此部分:
delete
delete from t where veh = 'V1' and loc not in ('A', 'Y');
并为 insert 这个 merge :
insert
merge
merge into t using (select 'V1' veh, 'A' loc from dual union all select 'V1' veh, 'Y' loc from dual) s on (t.veh = s.veh and t.loc = s.loc) when not matched then insert values (s.veh, s.loc);
地点 A 没有动过, B 和 X 被删除了 delete , Y 被添加 merge 。如果表中有更多列,则可以在一个列中执行整个操作 merge ,但我不知道它是否会更快,因为它需要加入源查询。
的 编辑: 强> 您必须以某种方式构建您的“消息”到Oracle可读的数据结构中。也许消息已存储在某些表中,也许您可以使用临时结构。在你的问题中你没有准确。 我给你举了一个关于双重的例子,因为我不得不以某种方式构造语句。对于 V1(A, B, C) 和 V3(X, Y) 你可以做 union all 5次或使用较短的语法:
V1(A, B, C)
V3(X, Y)
union all
select 'V1' veh, column_value loc from table(sys.odcivarchar2list('A', 'B', 'C')) union all select 'V3' veh, column_value loc from table(sys.odcivarchar2list('X', 'Y'))
sys.odcivarchar2list 是Oracle预定义类型,您也可以定义自己的类型( create type locations as table of varchar2(100) )并使用它。
sys.odcivarchar2list
create type locations as table of varchar2(100)
无论如何,跑 delete 每辆车两次:
delete from t where veh = `V1` and loc not in ('A', 'B', 'C'); delete from t where veh = `V3` and loc not in ('X', 'Y');
和 merge 一旦:
merge into t using ( select 'V1' veh, column_value loc from table(sys.odcivarchar2list('A', 'B', 'C')) union all select 'V3' veh, column_value loc from table(sys.odcivarchar2list('X', 'Y'))) s on (t.veh = s.veh and t.loc = s.loc) when not matched then insert values (s.veh, s.loc);