Системы обработки информации - язык баз данных SQL

       

Новый оператор обновления базы данных MERGE


В приложениях SQL-ориентированных баз данных часто возникает потребность в передаче множества строк из таблицы, обновлявшейся при выполнении транзакции (транзакционной таблицы), в некоторую основную таблицу базы данных. Обычно транзакционная таблица содержит обновленные варианты строк, существующих в основной таблице, а также, возможно, новые строки, которые должны быть занесены в основную таблицу. При наличии традиционных средств обновления базы данных содержимое транзакционной таблицы может быть перенесено в основную таблицу путем выполнения двух отдельных шагов. На первом шаге требуется выполнить оператор UPDATE для всех строк основной таблицы, для которых имеются модифицированные “двойники” в транзакционной таблице. Затем нужно выполнить оператор INSERT для занесения в основную таблицу всех строк транзакционной таблицы, для которых таких двойников нет. Оператор MERGE, введенный в SQL:2003, позволяет выполнить такую операцию за один шаг, более эффективный и проще специфицируемый. Вот общий синтаксис этого нового оператора в немного упрощенной форме:

MERGE INTO table_name [ [ AS ] correlation_name ]
USING table_reference
ON conditional_expression merge_operation_specification

merge_operation_specification ::=
{ merge_when_matched_clause | merge when not matched clause }
| merge_when_matched_clause merge_when_not_matched_clause
| merge_when_not_matched_clause merge_when_matched_clause

merge_when_matched_clause ::=
WHEN MATCHED THEN UPDATE SET update_assignment_commalist

merge_when_not_matched_clause ::=
WHEN NOT MATCHED THEN INSERT [ ( column_commalist ) ]
VALUES ( value_expression_commalist )

Как видно из синтаксиса, в операторе обязательно содержится условное выражение и, по крайней мере, один из разделов “слияния при наличии сопоставления” (merge_when_matched_clause) и “слияния при отсутствии сопоставления” (merge when not matched clause). Пусть T1 обозначает таблицу, указанную в разделе USING, а T2 – имя таблицы, указанной в разделе INTO. Тогда семантика выполнения операции определяется следующим образом:


Во-вторых, очевидным образом не просматриваются разумные способы использования оператора MERGE, отличные от тривиальных случаев.

Приведем пример тривиального (хотя и вполне полезного и осмысленного) использования оператора. Предположим, что в базе данных предприятия поддерживается сводная таблица INVENTORY (инвентарная ведомость), содержащая данные обо всех деталях, которые имеются на предприятии. Дополнительные детали поступают на предприятие путем поставок от поставщиков, причем каждой поставке соответствует транзакционная таблица SHIPMENT. В завершение транзакции поставки требуется “перелить” данные из таблицы SHIPMENT в таблицу INVENTORY. Пусть таблицы SHIPMENT и INVENTORY имеют одну и ту же структуру, а наполнение их такое, какое показано на рис. 3.

INVENTORY



PART_NO

PART_NAME

PART_QUANTITY

1

Bolt

5

2

Screw

10

3

Nut

30

SHIPMENT

PART_NO

PART_NAME

PART_QUANTITY

1

Bolt

5

4

Nail

10

3

Nut

30

MERGE INTO INVENTORY ...

PART_NO

PART_NAME

PART_QUANTITY

1

Bolt

10

2

Screw

10

3

Nut

60

4

Nail

10

Рис. 3. Пример использования оператора MERGE

В обеих таблицах столбец PART_NO

является первичным ключом, а столбец PART_QUANTITY содержит данные о числе деталей в инвентарной ведомости или в поставке. Тогда в результате выполнения приведенного ниже оператора MERGE таблица INVENTORY

примет вид, показанный в нижней части рис. 3.

MERGE INTO INVENTORY AS INV
USING (SELECT PART_NO, PART_NAME, PART_QUANTITY FROM SHIPMENT) AS SH
ON (INV.PART_NO = SH.PART_NO)
WHEN MARCHED THEN UPDATE
SET PART_QUANTITY = INV.PART_QUANTUTY + SH.PART_QUANTITY

WHEN NOT MARCHED THEN INSERT
(PART_NO, PART_NAME, PART_QUANTITY)
VALUES (SH.PART_NO, SH.PART_NAME, SH.PART_QUANTITY) ;


Содержание раздела