как обновить таблицу базы данных списком данных - PullRequest
0 голосов
/ 05 марта 2019

Допустим, у меня есть таблица базы данных с двумя столбцами - vehicle и location.

Каждый vehicle имеет много locations.

Когда моя программа получает сообщение, содержащее список мест для каждого транспортного средства, я могу выполнить любое из следующих действий:

  1. Delete все места для транспортного средства и прокрутите сообщение, чтобы повторно insert их все (неэффективно)
  2. Select местоположения для транспортного средства из базы данных, переберите сообщение и создайте список тех местоположений, которые находятся в базе данных, но не в сообщении, и тех, которые находятся в сообщении, но не в базе данных. Удалите (DELETE WHERE IN...) те, которые находятся в БД, но не в сообщении, и insert те, которые находятся в сообщении, но не в базе данных.

Это то, где мое знание SQL подводит меня. Есть ли более эффективный способ (т. Е. Меньше операторов SQL, меньше времени БД, меньше блокировок) для этого (я не могу выполнять хранимые процедуры)?

Мой инстинкт подсказывает мне, что я должен быть в состоянии сделать DELETE WHERE NOT IN..., чтобы избавиться от необходимости select из базы данных в варианте 2 - но тогда мне все еще нужно select, чтобы знать, какие дополнительные вставлять. Есть ли INSERT эквивалент - INSERT {THIS LIST OF locations} ALL WITH {this vehicle}, возможно? Или есть стандартная часть логики синхронизации, которая обычно используется в такой ситуации?

1 Ответ

0 голосов
/ 05 марта 2019

Допустим, у вас есть автомобиль V1 с местоположениями A, B и X и автомобиль V2 с местоположениями B и Q.Сообщение предназначено для автомобиля V1 с местоположениями A, Y.

Для delete детали вы можете использовать это:

delete from t where veh = 'V1' and loc not in ('A', 'Y');

и для insert this 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, но я не знаю, будет ли это быстрее, потому что это потребует объединения в исходном запросе.


Edit: Вы должны как-то встроить свое "сообщение" в структуру данных, читаемую Oracle.Возможно, сообщения уже хранятся в некоторой таблице, может быть, вы можете использовать временную структуру.Вы не уточнили это в своем вопросе.Я дал вам пример, работающий над двойным, потому что мне нужно было как-то создавать операторыДля V1(A, B, C) и V3(X, Y) вы можете сделать union all 5 раз или использовать более короткий синтаксис:

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))и использовать это.

В любом случае, выполните 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);
...