说我有一个包含两列的数据库表-vehicle
和location
。
每个vehicle
有很多locations
。
当程序接收到包含每辆车位置列表的消息时,我可以执行以下任一操作:
Delete
车辆的所有位置并遍历消息以重新insert
全部(效率低)Select
从数据库中获取车辆的位置,遍历消息并创建一个列表,其中列出了数据库中但消息中没有的位置,以及消息中但数据库中没有的位置。删除(DELETE WHERE IN...
)在数据库中但不在消息中的那些,insert
在消息中但不在数据库中的那些。这是我对SQL的了解使我失败的地方。有没有更有效的方法(即更少的SQL语句,更少的数据库时间,更少的锁定)来执行此操作(我无法执行存储过程)?
我的直觉告诉我,我必须能够做DELETE WHERE NOT IN...
,才能省去选项2中的数据库select
的麻烦-但是我仍然必须select
才能知道还有哪些插入。是否有任何INSERT
等效项-INSERT {THIS LIST OF locations} ALL WITH {this vehicle}
?还是在这种情况下通常使用标准的同步逻辑?
答案 0 :(得分:0)
比方说,您有V1
,A
和B
位置的车辆X
和V2
和{{1 }}。该消息用于位置为B
,Q
的车辆V1
。
对于A
部分,您可以使用:
Y
,对于delete
,delete from t where veh = 'V1' and loc not in ('A', 'Y');
:
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
中完成整个操作,但是我不知道这样做是否会更快,因为这需要在源查询中进行联接。
编辑:
您必须以某种方式将“消息”构建为Oracle可读的数据结构。也许消息已经存储在某个表中,也许您可以使用临时结构。您没有在问题中指出这一点。
我为您提供了处理双重对象的示例,因为我必须以某种方式构造语句。对于merge
和merge
,您可以执行V1(A, B, C)
5次或使用较短的语法:
V3(X, Y)
union all
是Oracle预定义类型,您也可以定义自己的(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
两次:
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');