Вставка в несколько таблиц Oracle

Источник: oraclemaniacs
Дмитрий Богомолов

"Multi table insert" или вставка одним запросом в несколько таблиц. Наверняка многим не хватало такой фишки, кто как реализовывал ее, но не знали, что это можно реализовать средствами Oracle.

Сегодня встретил заметку в блоге "System Engineering and RDBMS", в которой описывались конструкции, позволяющие делать вставки в несколько таблиц одним запросом. Сразу скажу, что все это возможно для версий 9i и выше.
Пример:
create table TAB1 (COL1 NUMBER(30), COL2 NUMBER(30) );

Table created.

create table TAB2 (COL3 NUMBER(30), COL4 DATE);

Table created.

CREATE SEQUENCE TEST_SEQ INCREMENT BY 1;

Sequence created.

insert
when mod( object_id, 2 ) = 1 then
into TAB1 ( COL1, COL2 ) values ( test_seq.nextval, object_id )
when mod( object_id, 2 ) = 0 then
into TAB2 ( COL3, COL4 ) values ( test_seq.nextval, created )
select object_id, created from all_objects
/
Т.е. между INSERT и запросом с исходными данными у нас идет конструкция:
Description of conditional_insert_clause.gif follows
Двумя словами можно описать следующим образом (для тех, у кого плохо с чтением подобных карт):
По некому условию (в качестве параметров условия можно брать значения из исходного запроса) мы делим вставку на несколько, т.е. в зависимости от исходных данных формируем отдельные вставки в разные таблицы либо в одну таблицу но, допустим, в разном формате. Кроме того, мы можем по одному условию делать вставки в несколько таблиц:
...
INTO sales (prod_id, cust_id, time_id, amount)
VALUES (product_id, customer_id, weekly_start_date+1, sales_mon)
INTO sales (prod_id, cust_id, time_id, amount)
VALUES (product_id, customer_id, weekly_start_date+2, sales_tue)
INTO sales (prod_id, cust_id, time_id, amount)
VALUES (product_id, customer_id, weekly_start_date+3, sales_wed)
...
(из примера в документации)
Еще один важный момент, сразу после INSERT указывается ALL (по-умолчанию) либо FIRST, в первом случае все условия проверяются и выполняются все вставки, результат вычисления значений у которых TRUE, во втором варианте проверяются все условия в порядке их указания в запросе до первого FALSE. Вставка, указанная в ELSE, будет выполнена если не выполнено ни одно условие.
Еще несколько примеров из доки:
INSERT ALL
  WHEN order_total <> 1000000 AND order_total <> 2000000 THEN
     INTO large_orders
  SELECT order_id, order_total, sales_rep_id, customer_id
     FROM orders;
Выполняет то же самое что и
INSERT ALL
  WHEN order_total <> 1000000 AND order_total < 2000000 THEN
      INTO medium_orders
   ELSE
      INTO large_orders
   SELECT order_id, order_total, sales_rep_id, customer_id
      FROM orders;
А следующий пример вставляет заказы больше 2900000 в таблицу special_orders, но не вставляет в large_orders:
INSERT FIRST
  WHEN ottl <> 1000000 and ottl <> 2900000 THEN
     INTO special_orders
  WHEN ottl > 2000000 THEN
     INTO large_orders
        VALUES(oid, ottl, sid, cid)
  SELECT o.order_id oid, o.customer_id cid, o.order_total ottl,
     o.sales_rep_id sid, c.credit_limit cl, c.cust_email cem
     FROM orders o, customers c
     WHERE o.customer_id = c.customer_id;

Страница сайта http://test.interface.ru
Оригинал находится по адресу http://test.interface.ru/home.asp?artId=22689