Die UPSERT-Operation aktualisiert oder fügt eine Zeile in eine Tabelle ein, je nachdem, ob die Tabelle bereits eine Zeile enthält, die mit den Daten übereinstimmt:
if table t has a row exists that has key X:
update t set mystuff... where mykey=X
else
insert into t mystuff...
Wie geht das am besten, da Oracle keine bestimmte UPSERT-Anweisung hat?
Die MERGE-Anweisung führt Daten zwischen zwei Tabellen zusammen. Mit DUAL können wir diesen Befehl verwenden. Beachten Sie, dass dies nicht gegen gleichzeitigen Zugriff geschützt ist.
quelle
Das Doppelbeispiel oben in PL / SQL war großartig, weil ich etwas Ähnliches tun wollte, aber ich wollte es clientseitig ... also hier ist das SQL, mit dem ich eine ähnliche Anweisung direkt von einem C # gesendet habe
Aus C # -Perspektive ist dies jedoch langsamer als das Aktualisieren und das Überprüfen, ob die betroffenen Zeilen 0 waren, und das Einfügen, falls dies der Fall war.
quelle
MERGE
DELETE
INSERT
MERGE INTO mytable d USING (SELECT 1 id, 'x' name from dual) s ON (d.id = s.id) WHEN MATCHED THEN UPDATE SET d.name = s.name WHEN NOT MATCHED THEN INSERT (id, name) VALUES (s.id, s.name);
Eine weitere Alternative ohne Ausnahmeprüfung:
quelle
quelle
Keine der bisher gegebenen Antworten ist angesichts gleichzeitiger Zugriffe sicher , wie in Tim Sylvesters Kommentar ausgeführt, und wird im Falle von Rennen Ausnahmen auslösen. Um dies zu beheben, muss die Einfüge- / Aktualisierungskombination in eine Art Schleifenanweisung eingeschlossen werden, damit im Falle einer Ausnahme das Ganze erneut versucht wird.
Als Beispiel sehen Sie, wie der Code von Grommit in eine Schleife eingeschlossen werden kann, um die Sicherheit bei gleichzeitiger Ausführung zu gewährleisten:
NB Im Transaktionsmodus
SERIALIZABLE
, den ich übrigens nicht empfehle, kann ORA-08177 auftreten: Der Zugriff für diese Transaktionsausnahmen kann stattdessen nicht serialisiert werden.quelle
Ich möchte, dass Grommit antwortet, außer dass es betrogene Werte erfordert. Ich habe eine Lösung gefunden, bei der sie möglicherweise einmal angezeigt wird: http://forums.devshed.com/showpost.php?p=1182653&postcount=2
quelle
INSERT (B.CILT, B.SAYFA, B.KUTUK, B.MERNIS_NO) VALUES (E.CILT, E.SAYFA, E.KUTUK, E.MERNIS_NO);
?Ein Hinweis zu den beiden Lösungen, die Folgendes vorschlagen:
1) Einfügen, wenn Ausnahme, dann aktualisieren,
oder
2) Aktualisieren, wenn sql% rowcount = 0, dann einfügen
Die Frage, ob zuerst eingefügt oder aktualisiert werden soll, ist ebenfalls anwendungsabhängig. Erwarten Sie mehr Beilagen oder mehr Updates? Derjenige, der am wahrscheinlichsten Erfolg hat, sollte zuerst gehen.
Wenn Sie den falschen auswählen, erhalten Sie eine Reihe unnötiger Indexlesevorgänge. Keine große Sache, aber dennoch etwas zu beachten.
quelle
Ich verwende seit Jahren das erste Codebeispiel. Beachten Sie nicht gefunden, anstatt zu zählen.
Der folgende Code ist der möglicherweise neue und verbesserte Code
Im ersten Beispiel führt das Update eine Indexsuche durch. Es muss, um die rechte Zeile zu aktualisieren. Oracle öffnet einen impliziten Cursor und verwendet ihn, um eine entsprechende Einfügung zu verpacken, damit wir wissen, dass die Einfügung nur erfolgt, wenn der Schlüssel nicht vorhanden ist. Die Einfügung ist jedoch ein unabhängiger Befehl und muss eine zweite Suche durchführen. Ich kenne das Innenleben des Befehls merge nicht, aber da der Befehl eine einzelne Einheit ist, hätte Oracle die korrekte Einfügung oder Aktualisierung mit einer einzelnen Indexsuche ausführen können.
Ich denke, Zusammenführen ist besser, wenn Sie eine Verarbeitung durchführen müssen, dh Daten aus einigen Tabellen entnehmen und eine Tabelle aktualisieren, möglicherweise Zeilen einfügen oder löschen. Für den Fall einer einzelnen Zeile können Sie jedoch den ersten Fall in Betracht ziehen, da die Syntax häufiger verwendet wird.
quelle
Kopieren und Einfügen eines Beispiels zum Einfügen einer Tabelle in eine andere mit MERGE:
Ergebnis:
quelle
Versuche dies,
quelle
Von http://www.praetoriate.com/oracle_tips_upserts.htm :
"In Oracle9i kann ein UPSERT diese Aufgabe in einer einzigen Anweisung ausführen:"
quelle