powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Просьба проверить, правильно ли я проверяю MERGE
7 сообщений из 7, страница 1 из 1
Просьба проверить, правильно ли я проверяю MERGE
    #39345248
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть историческая таблица data (data_id, item_id, attr_id, value, date_beg, date_end).
Есть такой запрос:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
select ...
, d.data_id
, ... as calc_actual
, ... as calc_value
from ...
join item i on (i.item_id = table.item_id and i.status > 0)
left join data d on (d.value like '000.__' and d.item_id = i.item_id and d.date_beg <= sysdate and nvl(d.date_end, DATE'9999-01-01') > sysdate)
left join attr a on (a.attr_id = i.attr_id and a.class = 'c1' and a.name = 'a1' and a.type_id = i.type_id)
where ...


Запрос возвращает подготовленные данные, которыми нужно обновить часть записей в таблице data.
Запрос на обновление будет примерно таким:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
merge into data
using (
select ...
, i.item_id
, d.data_id
, a.attr_id
, ... as calc_actual
, ... as calc_value
from ...
...
) rs on (rs.data_id = data.data_id)
when matched then
  update set data.value = nvl2(rs.calc_actual,rs.calc_value,data.VALUE), data.date_end = nvl2(rs.calc_actual,null,sysdate)
when not matched then
  insert (item_id, attr_id, value, date_beg, date_end)
  values (rs.item_id, rs.attr_id, rs.calc_value, sysdate, null)


Этот запрос должен добавить в таблицу data недостающие записи, "закрыть" существующие неактуальные записи и обновить существующие актуальные записи.
Но прежде чем его запускать, я хочу проверить область его действия (преобразовав MERGE в SELECT):
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
select nvl2(rs.data_id,'update','insert') as mode
, nvl2(rs.calc_actual,rs.calc_value,data.value) as update_value
, nvl2(rs.calc_actual,null,sysdate) as update_date_end
, rs.item_id as insert_item_id
, rs.attr_id as insert_attr_id
, rs.calc_value as insert_calc_value
, sysdate as insert_date_beg
, null as insert_date_end
from (
select ...
...
) rs
left join data on (rs.data_id = data.data_id)



Таблица data весьма важная и я очень опасаюсь поменять в ней что-нибудь лишнее.
Правильно ли я составил проверочный запрос?
То есть MERGE обновит только те строки, которые я вижу в проверочном SELECT, или может затронуть что-нибудь еще?

________________________
Мы смотрим с оптимизмом...
...в оптический прицел.
...
Рейтинг: 0 / 0
Просьба проверить, правильно ли я проверяю MERGE
    #39345348
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.Таблица data весьма важная и я очень опасаюсь поменять в ней что-нибудь лишнее.
Правильно ли я составил проверочный запрос?А кому ты будешь предъявлять претензию, если после наших "советов" тебя уволят за неподобающее отношение квалификация/ответственность?
...
Рейтинг: 0 / 0
Просьба проверить, правильно ли я проверяю MERGE
    #39345388
XMLer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.,
Сделай копию таблицы и выполни над ней свой merge, проанализируй результаты.
...
Рейтинг: 0 / 0
Просьба проверить, правильно ли я проверяю MERGE
    #39345495
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спрошу по другому.
merge into dst using src эквивалентно (по области применения) select from src left join dst ?

XMLerСделай копию таблицы и выполни над ней свой merge, проанализируй результаты.
Да, спасибо за совет.
Вчера вечером я уже сам сообразил, обновляются только нужные записи (сравнивал исходную таблицу и копию по всем полям).
Правда не могу исключить того, что что-то все же упустил и на другом наборе данных это может вылезти.
...
Рейтинг: 0 / 0
Просьба проверить, правильно ли я проверяю MERGE
    #39345806
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.,

Хороший стиль - это исключить какую-либо логику в кляузах matched/not matched.
То есть внедряемый набор данных должен в точности быть получен в using.
Имея его, можешь проверять сколько угодно.

Можно пойти дальше и в using приджойнить к итоговой таблице.
Так ты получишь точный snapshot таблицы после merge.
Потом в саму таблицу можно смерджить по roiwd. Но при таком подходе будет один избыточный джойн (с итоговой таблицей).
Merge обновит только те строки для которых rowid в using будет is not null.

А, да, в Oracle есть конструкция rollback если что.
...
Рейтинг: 0 / 0
Просьба проверить, правильно ли я проверяю MERGE
    #39345858
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dbms_photoshopМожно пойти дальше и в using приджойнить к итоговой таблице.
Я именно так и делаю, по условию соединения on (rs.data_id = data.data_id) это видно (data.data_id это PK).
Но что-то лишнее обновить было бы крайне не желательно. И rollback не поможет, потому что это может вылезти только через месяц.
Поэтому мне и нужен визуальный контроль, чтобы глазами просмотреть строки, которые попадут под обновление.
Если запрос типа from src left join dst полностью соответствует логике работы merge, то этого достаточно.
Главное чтобы у merge не было каких-нибудь особенностей, из-за которых область действия может оказаться шире.

В matched/not matched совсем без логики обойтись не получается, есть вычисляемое поле CALC_ACTUAL, которое дает некоторую нелинейность (использование функции nvl2).
С этим не будет проблем?
Код: plsql
1.
2.
3.
4.
5.
when matched then
  update set data.VALUE = nvl2(rs.CALC_ACTUAL,rs.CALC_DISCOUNT,data.VALUE), data.DATE_END = nvl2(rs.CALC_ACTUAL,null,trunc(sysdate)+1)
when not matched then
  insert (SERVICE_ID, DICT_ID, VALUE, DATE_BEG, DATE_END)
  values (rs.SERVICE_ID, rs.DISCOUNT_DICT, rs.CALC_DISCOUNT, trunc(sysdate)+1, null)
...
Рейтинг: 0 / 0
Просьба проверить, правильно ли я проверяю MERGE
    #39345873
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.,

Еще раз.
Всегда. Абсолютно всегда, если в using есть соединение с итоговой таблицей , то можно получить в точности итоговый набор избежав какой-либо логики вне using. Соединение в merge указывать по rowid . Если rowid в using null, то строка будет вставлена, иначе - обновлена.
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Просьба проверить, правильно ли я проверяю MERGE
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]