Verwenden der Einfügung mehrerer Tabellen für übergeordnete und untergeordnete Tabellen

8

Ist es sicher, die Einfügeanweisung für mehrere Tabellen von Oracle zum Einfügen in eine übergeordnete und untergeordnete Tabelle (mit Fremdschlüsselbeschränkung) zu verwenden?

Mit minimalen Beispielen habe ich festgestellt, dass es funktioniert, solange die übergeordnete Tabelle vor der untergeordneten Tabelle in der intoListe steht. Kann ich mich darauf verlassen oder sollte ich die Einschränkung aufschieben?

Isaac Kleinman
quelle
Sprechen Sie über INSERT ALL?
Philᵀᴹ
@Phil: Ja das bin ich.
Isaac Kleinman
Was ist mit zwei Einsätzen? Warum mit aufschiebbaren Einschränkungen den Kreisverkehr gehen, wenn die einfache Methode der Mehrfacheinfügungen immer funktioniert hat?
Vincent Malgrat
1
@ Vincent manchmal dauert es einen Bruchteil der Zeit, um insert all- das kann Isaacs Grund sein?
Jack sagt, versuchen Sie es mit topanswers.xyz
@ JackDouglas Leistung ist ein guter Grund, hat aber INSERT ALLviele Einschränkungen: keine parallele Ausführung, kein Einfügen in eine Ansicht. Dies lässt mich denken, dass diese Anweisung weniger optimiert ist als Standardanweisungen INSERT, insbesondere beim Einfügen in mehrere Tabellen.
Vincent Malgrat

Antworten:

7

Nein , darauf können Sie sich nicht verlassen. SQL ist deklarativ und nicht prozedural. Daher können Sie innerhalb einer Anweisung die Ausführungsreihenfolge nicht garantieren. Da die gesamte INSERT ALLAnweisung als einzelne Anweisung ( doc ) betrachtet wird, können Sie nicht garantieren, dass eine INSERTvor der anderen steht.

Per Definition INSERT FIRSTmuss ein erstes Ausführen INTOder bewerteten Bedingungen ausgeführt werden. Wir könnten erwarten INSERT ALL, dass wir uns ähnlich verhalten. Dies scheint der Fall zu sein:

DROP TABLE T1;
CREATE TABLE T1 AS (SELECT 'a' c1, 0 c2, 0 c3 FROM dual WHERE 1=2);
INSERT ALL 
   WHEN mod(x,2)<>0 THEN INTO T1 VALUES ('a', x, mod(x,2)) 
   WHEN mod(x,2)=0 THEN INTO T1 VALUES ('b', x, mod(x,2)) 
   SELECT Level x FROM dual CONNECT BY Level <=20;
COMMIT;   
SELECT rowid, c1, c2, c3 FROM t1;

Obwohl wir ein bestimmtes Verhalten auf einer bestimmten Plattform / Version / Patchset demonstrieren können, ist dies dennoch keine Garantie.

Oracle-developer.net sagt es ausdrücklich:

Die Bedingungen in einer INSERT FIRST-Anweisung werden in der Reihenfolge von oben nach unten ausgewertet. Oracle übernimmt keine solchen Garantien mit einer INSERT ALL-Anweisung.

Leigh Riffel
quelle
1
Oracle betrachtet dieses nicht deterministische Verhalten tatsächlich als Fehler (Fehler 2891576 finden Sie in My Oracle Support-Artikel 265826.1). Angesichts der Tatsache, dass dies bereits 2003 für Version 9.2.0.3 veröffentlicht wurde, bezweifle ich, dass die Wahrscheinlichkeit groß ist, dass dies bald behoben wird.
Chris Saxon
1
@ Chris Saxon Ausgezeichneter Fund. Der Bericht zeigt einen Fall, in dem sich das Ändern der Größe einer nicht verwandten Spalte darauf auswirkt, welche zuerst ausgeführt wird. Wie erwartet ist die Problemumgehung zu verwenden DEFERRED CONSTRAINTS.
Leigh Riffel
2

Isaac,

Sie können sich nicht darauf verlassen, da Orakel die Bestellung von INSERT nicht garantiert. Der richtige Weg, dies zu tun, ist, wie Sie erwähnt haben, die verzögerte Fremdschlüsseleinschränkung.

Narendra
quelle
Die Reihenfolge spielt keine Rolle, da die Einschränkungen nach Ausführung des SQL-Befehls überprüft werden . Nun, theoretisch funktioniert es aufgrund des oben erwähnten Fehlers nicht richtig. Sehen Sie sich ein Beispiel mit einem INSERT ... SELECThier an: sqlfiddle.com/#!15/7de0f (beachten Sie, dass es mit PostreSQL und Oracle funktioniert, aber nicht mit MySQL oder MS SQL)
David Balažic