Слияние наборов данных
Оператор MERGE
производит слияние записей источника в целевую таблицу (или
обновляемое представление). Источником может быть таблица, представление, хранимая
процедура или производная таблица. Каждая запись источника используется для
обновления (предложение UPDATE
) или удаления (предложение DELETE
) одной или более
записей цели, или вставки (предложение INSERT
) записи в целевую таблицу, или ни для того,
ни для другого. Условие обычно содержит сравнение столбцов в таблицах источника и цели.
Синтаксис оператора MERGE
:
MERGE INTO target [[AS] target_alias]
USING <source> [[AS] source_alias] ON <join condition> <merge when> [<merge when> ...]
[RETURNING <returning_list> [INTO <variable_list>]]
<merge when> ::= <merge when matched> | <merge when not matched>
<merge when matched> ::= WHEN MATCHED [ AND <condition> ]
THEN { UPDATE SET <assignment_list> | DELETE }
<merge when not matched> ::= WHEN NOT MATCHED [ AND <condition> ]
THEN INSERT [ (<column_list>) ] VALUES (<value_list>)
Допускается указывать несколько предложений WHEN MATCHED
и WHEN NOT MATCHED
.
Предложения WHEN
проверяются в указанном порядке. Если условие в предложении WHEN
не выполняется, то мы пропускаем его и переходим к следующему предложению. Так будет
происходить до тех пор, пока условие для одного из предложений WHEN
не будет выполнено.
В этом случае выполняется действие, связанное с предложением WHEN
, и осуществляется
переход на следующую строку источника. Для каждой строки источника выполняется только
одно действие.
Примеры:
MERGE INTO books b
USING purchases p ON p.title = b.title AND p.booktype = 'bk'
WHEN MATCHED THEN
UPDATE SET b.descr = b.descr || '; ' || p.descr
WHEN NOT MATCHED THEN
INSERT (title, descr, bought) VALUES (p.title, p.descr, p.bought);
С использованием производной таблицы.
MERGE INTO customers c
USING (SELECT * FROM customers_delta WHERE id > 10) cd ON (c.id = cd.id)
WHEN MATCHED THEN
UPDATE SET name = cd.name
WHEN NOT MATCHED THEN
INSERT (id, name) VALUES (cd.id, cd.name);
С использованием предложения DELETE
MERGE INTO SALARY_HISTORY
USING (
SELECT EMP_NO FROM EMPLOYEE WHERE DEPT_NO = 120) EMP
ON SALARY_HISTORY.EMP_NO = EMP.EMP_NO
WHEN MATCHED THEN DELETE
В следующем примере происходит ежедневное обновление таблицы PRODUCT_IVENTORY
на
основе заказов, обработанных в таблице SALES_ORDER_LINE
. Если количество заказов на
продукт таково, что уровень запасов продукта опускается до нуля или становится ещё ниже, то
строка этого продукта удаляется из таблицы PRODUCT_IVENTORY
.
MERGE INTO PRODUCT_IVENTORY AS TARGET
USING (
SELECT SL.ID_PRODUCT, SUM(SL.QUANTITY)
FROM SALES_ORDER_LINE SL
JOIN SALES_ORDER S ON S.ID = SL.ID_SALES_ORDER
WHERE S.BYDATE = CURRENT_DATE
GROUP BY 1
) AS SRC(ID_PRODUCT, QUANTITY)
ON TARGET.ID_PRODUCT = SRC.ID_PRODUCT
WHEN MATCHED AND TARGET.QUANTITY - SRC.QUANTITY <= 0 THEN
DELETE
WHEN MATCHED THEN
UPDATE SET TARGET.QUANTITY = TARGET.QUANTITY - SRC.QUANTITY, TARGET.BYDATE = CURRENT_DATE