Oracle SQL-эквивалент массовой вставки MySQL

У меня есть такая таблица:

email (primary-key) | first_contact_date | last_contact_date | due_date | status

Пользователь может загрузить в таблицу таблицу Excel из другого приложения. Эксель содержит:

email | first_contact_date | last_contact_date 

После загрузки пользователь может изменить (обновить) статус и дату выполнения.

Однако примерно раз в неделю пользователь будет загружать последнюю электронную таблицу Excel, содержащую новые И старые записи. Другими словами, некоторые строки уже существуют в таблице и над ними уже работали.

По этой причине мы не можем удалить существующие записи. Вместо:

  • если запись новая, вставьте
  • если запись уже существует в таблице (т.е. электронная почта существует), нам нужно обновить last_contact_date

Электронная таблица Excel может содержать от 1000 до 50 000 строк.

Каков наиболее эффективный подход к вставке записей в Oracle?? В mySQL я просто использовал пакетную вставку с «обновлением дубликатов», но у Oracle нет этой функции.

Какой подход лучше выбрать??

Любая помощь приветствуется.


person DrBorrow    schedule 10.08.2019    source источник
comment
Oracle SQL имеет такую ​​возможность благодаря оператору MERGE. Но вы спрашиваете о необработанном операторе SQL или эту функциональность нужно использовать через вашу структуру?   -  person Jon Heller    schedule 11.08.2019
comment
Он используется в нескольких местах, но мне просто нужно увидеть один рабочий синтаксис, и я могу взять его оттуда. В настоящее время я перехожу с MySQL на Oracle, и это единственный фрагмент кода, который не так легко переносится. Спасибо!   -  person DrBorrow    schedule 11.08.2019


Ответы (2)


MERGE немного сложен. Но его стоит использовать здесь, потому что это быстрее, чем использование некоторой комбинации операторов UPDATE и INSERT.

--Create table and initial data.
create table contacts
(
    email varchar2(100) primary key,
    first_contact_date date,
    last_contact_date date,
    due_date date,
    status varchar2(100)
);

insert into contacts values('[email protected]', sysdate, sysdate, sysdate, 'open');
insert into contacts values('[email protected]', sysdate, sysdate, sysdate, 'open');
commit;


--Merge (upsert) new rows into the table.
merge into contacts
using
(
    select '[email protected]' email, date '2000-01-01' first_contact_date, date '2000-01-01' last_contact_date from dual union all
    select '[email protected]' email, date '2000-01-01' first_contact_date, date '2000-01-01' last_contact_date from dual
) new_contacts
on (contacts.email = new_contacts.email)
when matched then update set
    contacts.first_contact_date = new_contacts.first_contact_date,
    contacts.last_contact_date = new_contacts.last_contact_date
when not matched then insert
    values(new_contacts.email, new_contacts.first_contact_date, new_contacts.last_contact_date, null, null);

Кстати, вы сказали, что выполняете миграцию с MySQL на Oracle? Я не знал, что это был противоположный день.

person Jon Heller    schedule 10.08.2019
comment
Это очень полезно! Чем ты. Завтра проверю и отмечу как ответ - person DrBorrow; 11.08.2019
comment
Относительно MySQL: да, я очень неохотно перехожу ИЗ MySQL. Наш ИТ-отдел говорит, что Oracle лучше. Лично я не вижу преимущества!! Если бы у меня были доказательства обратного, я бы с удовольствием помахал ими! :-) - person DrBorrow; 11.08.2019
comment
Исходя из моего ограниченного опыта работы с MySQL, я думаю, что синтаксис Oracle SQL и PL/SQL более мощный, что может привести к более простому коду и повышению производительности. Но программное обеспечение стоит гору денег. Я предполагаю, что ваш ИТ-отдел не обращает внимания на цену. Когда-нибудь у бухгалтера будет неприятный разговор с техническим директором, и вы мигрируете обратно. Но эй, по крайней мере, это дает вам некоторую безопасность работы. - person Jon Heller; 11.08.2019

В Yii 2 есть upsert(), который работает так, как вы хотите, но поддерживает только вставку/обновление одной записи. Таким образом, с 50 000 записей вам нужно 50 000 запросов upsert — определенно не самое эффективное решение, но, по крайней мере, синтаксис прост и защищает вас от состояния гонки (операция атомарна):

Yii::$app->db->createCommand()
    ->upsert($tableName, $row, ['last_contact_date' => $row['last_contact_date'])
    ->execute();
person rob006    schedule 11.08.2019