Вопрос:

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

plsql yii2 oracle12c on-duplicate-key batch-insert

20 просмотра

2 ответа

560 Репутация автора

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

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

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

email | first_contact_date | last_contact_date 

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

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

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

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

Таблица Excel может содержать от 1000 до 50000 строк.

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

Каков наилучший подход?

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

Автор: DrBorrow Источник Размещён: 10.08.2019 10:30

Ответы (2)


1 плюс

26266 Репутация автора

MERGEСинтаксис Oracle немного хитрый. Но это стоит использовать здесь , потому что это быстрее , чем при использовании некоторой комбинации 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('a@a.com', sysdate, sysdate, sysdate, 'open');
insert into contacts values('b@b.com', sysdate, sysdate, sysdate, 'open');
commit;


--Merge (upsert) new rows into the table.
merge into contacts
using
(
    select 'b@b.com' email, date '2000-01-01' first_contact_date, date '2000-01-01' last_contact_date from dual union all
    select 'c@c.com' 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? Я не знал, что это был противоположный день.

Автор: Jon Heller Размещён: 10.08.2019 11:34

0 плюса

12502 Репутация автора

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

Yii::$app->db->createCommand()
    ->upsert($tableName, $row, ['last_contact_date' => $row['last_contact_date'])
    ->execute();
Автор: rob006 Размещён: 11.08.2019 08:35
Вопросы из категории :
32x32