Всем привет!

Хотел бы написать сегодня про «сложный» апдейт данных в Oracle с помощью нескольких таблиц. Все разработчики БД знают про то, как обновлять данные, это одно из самых первых, что все изучают. Я не буду в этой статье лить воду, те, кто мало знаком с апдейтом в принципе, думаю, необходимо прочитать что это такое и с чем это едят, а тем кто уже считает себя опытным — прошу! Итак, самый простой update выглядит так:

UPDATE table1
SET column1='Новосибирск'
WHERE column1='Сахалин'

Но что делать, когда нужно обновить данные в одной таблице, исходя из данных в другой таблице? Хм..давайте сделаем это :)  Недавно, на работе, увидел как коллега запустил обновление таблички, посмотрев через специальный скрипт (напишу потом отдельно по этому скрипту статью), что он делает, какой у него код и самое главное — сколько скрипт будет выполняться (да, oracle может показывать время окончания из специальных служебных таблиц) я просто офигел — выполнения скрипта должно окончиться, эдак через 5 дней :) Виной всему неоптимизированный алгоритм выполенения апдейта. Итак, приступим.

Допустим, у нас существуют 2 таблички, у которых есть одинаковое поле для объединения (обязательное условие) , например, номер договора. В таблице 1 также есть адрес магазина и клиента, а в таблице 2 тоже какая-нибудь инфа и более корректные адреса магазина и адреса клиентов (можете что-то свое придумать). В итоге нам нужно из 2 таблицы взять эти корректные адреса магазинов и клиентов и подставить в 1 таблицу. Пишем запрос:

UPDATE
(
SELECT
       t.adress_shop,
       t.adress_client,
       s.adress_shop AS adress_shop_new,
       s.adress_client AS adress_client_new
 
FROM table1 t
INNER JOIN table2 s ON s.ur_number=t.ur_number
)
tt
SET tt.adress_shop=tt.adress_shop_new, tt.adress_client=tt.adress_client_new

Я думаю вы тут все поняли, что и как. Немного поясню — выбираем поля, которые нужно обновить из первой таблицы, также тут же выбираем из второй таблицы, на которые нужно обновить. Все это добро цепляем по номеру договору (не забываем про дубликаты). Также тут специально использовал одинаковые название полей, чтобы хоть как-то усложнить, сделал 2 поля для обновления после «set», а то просто возникал как-то вопрос, как обновить одновременно 2 поля.

Здесь я использовал «inner join», но можете любой join  - кому как угодно, в зависимости от посталенной задачи и производительности. Соответсвенно, в join’е можно использовать несколько таблиц. Думаю, все знают как джоиниться к другим таблицам, это описывать я не буду, в любой книге найти можно. Я лишь хотел показать то, что уже не в каждой книге найдешь. Когда начинал работать с Oracle вставали у меня вопросы такого апдейта, мне в свое время помогли, когда был начинающий, теперь хочу помочь вам :) Кстати, есть еще один способ сделать такой же апдейт, но через «merge» — это оператор для «insert», «delete» и «update». Напишу скрипт с небольшими пояснениями, если будет что непонятно — всегда можете задать вопрос:

MERGE INTO table1 t
 
USING (SELECT * FROM table2 s) p
  ON (p.ur_number=t.ur_number)
 
WHEN MATCHED THEN--когда совпали договора, то идет сам update
 
UPDATE SET t.adress_shop=p.adress_shop_new, t.adress_client=p.adress_client_new
 
WHEN NOT MATCHED THEN INSERT (t.adress_shop) VALUES ('Ничего не нашел')

Кстати, 2 вариант считается уже более высокого уровня. Он показывает, что вы знакомы со сложным апдейтом, а также умеете работать с оператором «merge».

Плюс второго способа в том, что можно вставить какое-то дефолтное значение, если наше условие сцепки не сработало. Кстати, это все работает и в Oracle 10g, в 9 версии тоже.

Надеюсь, было все понятно и кому-то пригодится это.

Удачи!