=====Upsert - Mit dem Oracle Merge auf der gleichen Tabelle in einem Befehl ein Update/Insert nach Bedarf durchführen===== ==== Normale Lösung mit Update ==== Erst suchen, ob es den Wert schon gibt (count(*)) und dann falls ja => ein "**update**", falls kein Datensatz gefunden => ein "**insert**" durchführen. Oder viel einfacher das "**update**" versuchen und auf **SQL%ROWCOUNT** abfragen. begin update admin_props set property = 'DIF' where property = 'EXPORT_TYPE'; if sql%rowcount = 0 then dbms_output.put_line('-- Insert the value'); insert into admin_props (id, description, property, value) values (1 , 'Type of the interface' , 'EXPORT_TYPE' , 'DIF' ); else dbms_output.put_line('-- values was updated'); end if; end; Damit benötigen wir aber immer auch etwas PL/SQL um das umzusetzen. ---- ==== Lösung mit dem Merge Commando ==== Das **Merge** Kommando prüft mit der **ON** Klausel auf Gleichheit, nur wenn WERT1=WERT2 = TRUE wird der Match Block durchgeführt. Wir wollen nun, falls der Wert noch nicht in der Tabelle existiert, den Wert neu hinzufügen. Falls er aber schon existiert soll der Wert nur aktualisiert werden. Im ersten Schritt prüfen wir also in der **USING** Klausel mit einem Select auf die gleiche Tabelle, ob es den Wert schon gibt. Das funktioniert aber nicht! Ist der Datensatz nicht in der Tabelle enthalten gibt eine einfache Abfrage kein Ergebnis zum Vergleichen aus! Und damit vergleichen wir NICHTS mit etwas in der ON Klausel => das klappt nicht! Daher müssen wir mit der Union Anweisung in der SQL Abfrage ein Ergebnis aus dieser Abfrage erzwingen, so das wenigstens eine Zeile zum Vergleich zurück gegeben wird. Dies Zeile muss dann den gewünschten ID Value enthalten! Sonst funktioniert der nächste Update nicht, da ja wieder neu eingefügt wird für die "erzeugte" ID aus der Dual Abfrage! Soll ein Merge auf die gleiche Tabelle durchgeführt werden, muss das using select also immer min eine Zeile mit der richtigen ID für das Insert zurückgeben! merge into admin_props p using (select id from admin_gcm_props where property = 'EXPORT_TYPE' union select 1 from dual) t on (p.id = t.id) when matched then update set property = 'DIF' when not matched then insert (id, description, property, value) values ( t.id , 'Type of the interface' , 'EXPORT_TYPE' , 'DIF' ); ---- ===Mögliche Fehler === ORA-30926: unable to get a stable set of rows in the source tables Darauf achten das die using Klausel select Abfrage keine doppelten Werte liefert! ---- ==== Quellen ==== Für zwei unterschiedliche Tabellen siehe [[prog:sql_update_syntax|Oracle SQL - Update und Merge mit Daten in einer Tabelle mit Werten aus einer zweiten Tabelle]] Doku: Update: * https://docs.oracle.com/database/121/SQLRF/statements_10008.htm#SQLRF01708 Merge: * https://docs.oracle.com/database/121/SQLRF/statements_9016.htm#SQLRF01606