"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 и запросом с исходными данными у нас идет конструкция:

Двумя словами можно описать следующим образом (для тех, у кого плохо с чтением подобных карт):
По некому условию (в качестве параметров условия можно брать значения из исходного запроса) мы делим вставку на несколько, т.е. в зависимости от исходных данных формируем отдельные вставки в разные таблицы либо в одну таблицу но, допустим, в разном формате. Кроме того, мы можем по одному условию делать вставки в несколько таблиц:
...
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;