Wenn man im Merge-Statement die Aktualisierung im "when matched" Zweig auf Fälle beschränken will, bei denen sich tatsächlich Änderungen der Daten ergeben haben - was nicht nur aus Gründen der Performance eine gute Idee ist, sondern auch dann, wenn man in ETL-Operationen eine Historie von Veränderungen pflegen möchte, dann kann man dazu eine Where-Bedingung verwenden, die die Gleichheit neuer und existierender Werte für alle betroffenen Felder überprüft. Zu diesem Zweck habe ich in der Vergangenheit gelegentlich recht unübersichtliche OR-Verknüpfungen verwendet, bei denen NULL-Werte via COALESCE auf einen in den Daten nicht erscheinenden Wert gesetzt wurden. Eine deutlich elegantere Lösung zum Problem findet man bei Stew Ashton, der für dieses Mapping die DECODE-Funktion einsetzt. Dazu ein Beispiel:
drop table test_merge_src; create table test_merge_src as select rownum id , 1 col1 , 2 col2 from dual connect by level <= 10; select * from test_merge_src; ID COL1 COL2 ---------- ---------- ---------- 1 1 2 2 1 2 3 1 2 4 1 2 5 1 2 6 1 2 7 1 2 8 1 2 9 1 2 10 1 2 drop table test_merge_dest; create table test_merge_dest as select rownum id , 1 col1 , 2 col2 from dual connect by level <= 10; update test_merge_dest set col2 = null where id > 5; select * from test_merge_dest; ID COL1 COL2 ---------- ---------- ---------- 1 1 2 2 1 2 3 1 2 4 1 2 5 1 2 6 1 7 1 8 1 9 1 10 1 merge into test_merge_dest dst using (select * from test_merge_src) src on (src.id = dst.id) when matched then update set dst.col1 = src.col1 , dst.col2 = src.col2 where 1 in ( decode(dst.col1, src.col1, 0, 1) , decode(dst.col2, src.col2, 0, 1) ); 5 Zeilen zusammengeführt.
Natürlich kann diese Liste einzelner DECODE-Elemente auch recht unhandlich werden, bleibt aber in jedem Fall kompakter als eine Verknüpfung zahlloser OR-Elemente.
Nachtrag 20.01.2015: über Twitter bin ich von einem ehemaligen Kollegen an die Funktion SYS_OP_MAP_NONNULL erinnert worden, die man in diesem Zusammenhang natürlich auch einsetzen kann - und die seit 12c auch offiziell dokumentiert ist.
Nachtrag 20.01.2015: über Twitter bin ich von einem ehemaligen Kollegen an die Funktion SYS_OP_MAP_NONNULL erinnert worden, die man in diesem Zusammenhang natürlich auch einsetzen kann - und die seit 12c auch offiziell dokumentiert ist.
Keine Kommentare:
Kommentar veröffentlichen