Мне нужно синхронизировать две таблицы в Oracle. Я использовал MERGE для этой работы, но мне нужна помощь, чтобы получить работающий SQL для этого.
В моей целевой таблице есть PK и некоторые другие столбцы. Некоторые из этих столбцов не имеют нулевого ограничения.
Моя исходная таблица имеет другой формат и данные, чем моя целевая таблица, поэтому мне нужно запросить исходную таблицу и преобразовать данные в целевой макет.
Мой фактический код (упрощенно):
MERGE INTO TARGET t USING(
WITH SRC AS ( --do the transformation
SELECT ID, DECODE(VAL,'THIS','THAT','OTHER') VAL1, REGEXP_SUBSTR(VAL,'\d+') VAL2 FROM SOURCE
)
SELECT t.ROWID ROW_ID, s.* FROM SRC s
FULL OUTER JOIN TARGET t ON s.ID=t.ID
) s ON (t.ROWID=s.ROW_ID)
WHEN MATCHED THEN UPDATE SET t.VAL1=s.VAL1 AND t.VAL2=s.VAL2
DELETE WHERE s.ID IS NULL
WHEN NOT MATCHED THEN INSERT(ID, VAL1, VAL2) VALUES (s.ID, s.VAL1, s.VAL2);
Проблема в том, что эти строки, соответствующие условию DELETE, выдают ORA-01407: cannot update (string) to NULL
. Похоже, что Oracle сначала пытается обновить, а затем удалить. Это вызывает ОШИБКУ.
Ключевое слово MERGE действительно ужасно для синхронизации таблиц с удалением, но я бы хотел использовать один запрос, потому что мой SQL преобразования действительно тяжелый.
Есть ли какая-либо альтернатива MERGE или какое-либо предложение, что сделать, чтобы это работало?
Спасибо
Это мое решение. Может быть, это может кому-то помочь.
MERGE INTO TARGET t USING(
WITH SRC AS ( --do the transformation
SELECT ID, DECODE(VAL,'THIS','THAT','OTHER') VAL1, REGEXP_SUBSTR(VAL,'\d+') VAL2 FROM SOURCE
)
SELECT t.ROWID ROW_ID, NVL2(s.ID,null,1) delFlag, s.*
FROM SRC s
FULL OUTER JOIN TARGET t ON s.ID=t.ID
) s ON (t.ROWID=s.ROW_ID)
WHEN MATCHED THEN UPDATE SET t.VAL1=NVL2(s.delFlag,t.VAL1,s.VAL1) AND t.VAL2=NVL2(s.delFlag,t.VAL1,s.VAL2)
DELETE WHERE s.delFlag IS NOT NULL
WHEN NOT MATCHED THEN INSERT(ID, VAL1, VAL2) VALUES (s.ID, s.VAL1, s.VAL2);
Но действительно странно, что строки, которые будут удалены, должны пройти проверку ограничений.