Der beste Weg, um mehrzeilige Einfügungen in Oracle durchzuführen?


262

Ich suche nach einer guten Möglichkeit, mehrzeilige Einfügungen in eine Oracle 9-Datenbank durchzuführen. Das Folgende funktioniert in MySQL, scheint jedoch in Oracle nicht unterstützt zu werden.

INSERT INTO TMP_DIM_EXCH_RT 
(EXCH_WH_KEY, 
 EXCH_NAT_KEY, 
 EXCH_DATE, EXCH_RATE, 
 FROM_CURCY_CD, 
 TO_CURCY_CD, 
 EXCH_EFF_DATE, 
 EXCH_EFF_END_DATE, 
 EXCH_LAST_UPDATED_DATE) 
VALUES
    (1, 1, '28-AUG-2008', 109.49, 'USD', 'JPY', '28-AUG-2008', '28-AUG-2008', '28-AUG-2008'),
    (2, 1, '28-AUG-2008', .54, 'USD', 'GBP', '28-AUG-2008', '28-AUG-2008', '28-AUG-2008'),
    (3, 1, '28-AUG-2008', 1.05, 'USD', 'CAD', '28-AUG-2008', '28-AUG-2008', '28-AUG-2008'),
    (4, 1, '28-AUG-2008', .68, 'USD', 'EUR', '28-AUG-2008', '28-AUG-2008', '28-AUG-2008'),
    (5, 1, '28-AUG-2008', 1.16, 'USD', 'AUD', '28-AUG-2008', '28-AUG-2008', '28-AUG-2008'),
    (6, 1, '28-AUG-2008', 7.81, 'USD', 'HKD', '28-AUG-2008', '28-AUG-2008', '28-AUG-2008');

Antworten:


165

Dies funktioniert in Oracle:

insert into pager (PAG_ID,PAG_PARENT,PAG_NAME,PAG_ACTIVE)
          select 8000,0,'Multi 8000',1 from dual
union all select 8001,0,'Multi 8001',1 from dual

Hier ist die Verwendung der from dualAnweisung zu beachten.

( Quelle )


6
Es gibt auch etwas namens "Alle
einfügen

4
Seien Sie wählerisch, aber die Formatierung ist sinnvoller, wenn Sie "Union all" am Ende jeder Auswahlzeile einfügen (mit Ausnahme der letzten).
Jamie

Ein Nachteil dabei ist , wir können nicht ein verwenden , sequnce.nextvalwie es in verboten ist unionvon select. Stattdessen können wir mit gehen INSERT ALL.
sql_dummy

5
@Jamie: Die Formatierung von Espo ist etwas intelligenter in dem Sinne, dass Sie sich beim Hinzufügen neuer Zeilen keine Gedanken darüber machen müssen, ob Sie sich in der letzten Zeile befinden oder nicht. Sobald Sie Ihre 2 ersten Auswahlen getroffen haben, können Sie die letzte Zeile (oder eine mittlere Zeile) einfach kopieren / einfügen und sich nur auf die Werte konzentrieren, die Sie ändern müssen. Dies ist ein gängiger Trick für viele andere Fälle in beliebigen Sprachen (Komma, Logikoperatoren plus ...). Es ist nur eine Gewohnheitssache, viele frühere Praktiken wurden überarbeitet, um sich mehr auf die Haftung des Codes als auf die Intuitivität zu konzentrieren.
Laurent.B

Was ist das Maximum für 12c?
Toolkit

361

In Oracle können Sie die folgende Syntax verwenden, um mehrere Zeilen mit den Spalten col1, col2 und col3 in die Tabelle t einzufügen:

INSERT ALL
   INTO t (col1, col2, col3) VALUES ('val1_1', 'val1_2', 'val1_3')
   INTO t (col1, col2, col3) VALUES ('val2_1', 'val2_2', 'val2_3')
   INTO t (col1, col2, col3) VALUES ('val3_1', 'val3_2', 'val3_3')
   .
   .
   .
SELECT 1 FROM DUAL;

54
Ich verstehe nicht was SELECT 1 FROM DUAL.
Jameshfisher

55
INSERT ALLerfordert eine SELECTUnterabfrage. Um dies zu umgehen, SELECT 1 FROM DUALwird eine einzelne Zeile mit Dummy-Daten angegeben.
Markus Jarderot

40
Wie unterscheidet sich dies von mehreren Einfügeanweisungen? Sie haben immer noch die Wiederholung der Spaltennamen, also scheinen Sie nicht viel zu gewinnen.
Burhan Ali

28
Ungefähr 10-12 Mehrere INSERT-Anweisungen werden auf meinem PC in 2 Sekunden ausgeführt, während die obige Syntax 1000 Datensätze pro Sekunde einfügen kann! Beeindruckt! Beachten Sie, dass ich mich erst am Ende verpflichte.
Kent Pawar

13
Dies funktioniert einwandfrei. Wenn Sie jedoch eine Sequenz einfügen, z. B. user.NEXTVAL, wird für jede Einfügung der gleiche Wert zurückgegeben. Sie können es manuell in die Einfügung alle einfügen und dann die Sequenz außerhalb der Einfügung aktualisieren.
user1412523

33

Verwenden Sie SQL * Loader. Es dauert ein wenig, aber wenn dies kein Einzelfall ist, lohnt es sich.

Tabelle erstellen

SQL> create table ldr_test (id number(10) primary key, description varchar2(20));
Table created.
SQL>

CSV erstellen

oracle-2% cat ldr_test.csv
1,Apple
2,Orange
3,Pear
oracle-2% 

Loader-Steuerdatei erstellen

oracle-2% cat ldr_test.ctl 
load data

 infile 'ldr_test.csv'
 into table ldr_test
 fields terminated by "," optionally enclosed by '"'              
 ( id, description )

oracle-2% 

Führen Sie den SQL * Loader-Befehl aus

oracle-2% sqlldr <username> control=ldr_test.ctl
Password:

SQL*Loader: Release 9.2.0.5.0 - Production on Wed Sep 3 12:26:46 2008

Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.

Commit point reached - logical record count 3

Einfügen bestätigen

SQL> select * from ldr_test;

        ID DESCRIPTION
---------- --------------------
         1 Apple
         2 Orange
         3 Pear

SQL>

SQL * Loader bietet viele Optionen und kann so ziemlich jede Textdatei als Eingabe verwenden. Sie können die Daten in Ihrer Steuerdatei sogar inline einfügen, wenn Sie möchten.

Hier ist eine Seite mit einigen weiteren Details -> SQL * Loader


Dies sollte
meiner Meinung

Die ID-Spalte in meiner Tabelle wird automatisch generiert. Kann ich das ID-Feld in der Loader-Steuerdatei einfach überspringen?
Thom DeCarlo

@Thom, verwenden Sie die sequence.nextval zB fruit_id "fruit_seq.nextval"in der
Spaltendefinition

50 Millionen Datensätze in wenigen Minuten. Weiter so
Toolkit

20

Wann immer ich dies tun muss, erstelle ich einen einfachen PL / SQL-Block mit einer lokalen Prozedur wie dieser:

declare
   procedure ins
   is
      (p_exch_wh_key INTEGER, 
       p_exch_nat_key INTEGER, 
       p_exch_date DATE, exch_rate NUMBER, 
       p_from_curcy_cd VARCHAR2, 
       p_to_curcy_cd VARCHAR2, 
       p_exch_eff_date DATE, 
       p_exch_eff_end_date DATE, 
       p_exch_last_updated_date DATE);
   begin
      insert into tmp_dim_exch_rt 
      (exch_wh_key, 
       exch_nat_key, 
       exch_date, exch_rate, 
       from_curcy_cd, 
       to_curcy_cd, 
       exch_eff_date, 
       exch_eff_end_date, 
       exch_last_updated_date) 
      values
      (p_exch_wh_key, 
       p_exch_nat_key, 
       p_exch_date, exch_rate, 
       p_from_curcy_cd, 
       p_to_curcy_cd, 
       p_exch_eff_date, 
       p_exch_eff_end_date, 
       p_exch_last_updated_date);
   end;
begin
   ins (1, 1, '28-AUG-2008', 109.49, 'USD', 'JPY', '28-AUG-2008', '28-AUG-2008', '28-AUG-2008'),
   ins (2, 1, '28-AUG-2008', .54, 'USD', 'GBP', '28-AUG-2008', '28-AUG-2008', '28-AUG-2008'),
   ins (3, 1, '28-AUG-2008', 1.05, 'USD', 'CAD', '28-AUG-2008', '28-AUG-2008', '28-AUG-2008'),
   ins (4, 1, '28-AUG-2008', .68, 'USD', 'EUR', '28-AUG-2008', '28-AUG-2008', '28-AUG-2008'),
   ins (5, 1, '28-AUG-2008', 1.16, 'USD', 'AUD', '28-AUG-2008', '28-AUG-2008', '28-AUG-2008'),
   ins (6, 1, '28-AUG-2008', 7.81, 'USD', 'HKD', '28-AUG-2008', '28-AUG-2008', '28-AUG-2008');
end;
/

12

Wenn Sie bereits die Werte haben, die Sie in eine andere Tabelle einfügen möchten, können Sie sie aus einer select-Anweisung einfügen.

INSERT INTO a_table (column_a, column_b) SELECT column_a, column_b FROM b_table;

Andernfalls können Sie eine Reihe von Anweisungen zum Einfügen einzelner Zeilen auflisten und mehrere Abfragen in großen Mengen senden, um Zeit für etwas zu sparen, das sowohl in Oracle als auch in MySQL funktioniert.

Die Lösung von @Espo ist auch eine gute Lösung, die sowohl in Oracle als auch in MySQL funktioniert, wenn Ihre Daten nicht bereits in einer Tabelle enthalten sind.


4

Sie können mit Schleife einfügen, wenn Sie zufällige Werte einfügen möchten.

BEGIN 
    FOR x IN 1 .. 1000 LOOP
         INSERT INTO MULTI_INSERT_DEMO (ID, NAME)
         SELECT x, 'anyName' FROM dual;
    END LOOP;
END;


0

Hier ist eine sehr nützliche Schritt-für-Schritt-Anleitung zum Einfügen mehrerer Zeilen in Oracle:

https://livesql.oracle.com/apex/livesql/file/content_BM1LJQ87M5CNIOKPOWPV6ZGR3.html

Der letzte Schritt:

INSERT ALL
/* Everyone is a person, so insert all rows into people */
WHEN 1=1 THEN
INTO people (person_id, given_name, family_name, title)
VALUES (id, given_name, family_name, title)
/* Only people with an admission date are patients */
WHEN admission_date IS NOT NULL THEN
INTO patients (patient_id, last_admission_date)
VALUES (id, admission_date)
/* Only people with a hired date are staff */
WHEN hired_date IS NOT NULL THEN
INTO staff (staff_id, hired_date)
VALUES (id, hired_date)
  WITH names AS (
    SELECT 4 id, 'Ruth' given_name, 'Fox' family_name, 'Mrs' title,
           NULL hired_date, DATE'2009-12-31' admission_date
    FROM   dual UNION ALL
    SELECT 5 id, 'Isabelle' given_name, 'Squirrel' family_name, 'Miss' title ,
           NULL hired_date, DATE'2014-01-01' admission_date
    FROM   dual UNION ALL
    SELECT 6 id, 'Justin' given_name, 'Frog' family_name, 'Master' title,
           NULL hired_date, DATE'2015-04-22' admission_date
    FROM   dual UNION ALL
    SELECT 7 id, 'Lisa' given_name, 'Owl' family_name, 'Dr' title,
           DATE'2015-01-01' hired_date, NULL admission_date
    FROM   dual
  )
  SELECT * FROM names

0

In meinem Fall konnte ich eine einfache Einfügeanweisung verwenden, um viele Zeilen mit nur einer Spalte aus TABLE_B in TABLE_A einzufügen und die anderen Daten an anderer Stelle abzurufen (Sequenz und fest codierter Wert):

INSERT INTO table_a (
    id,
    column_a,
    column_b
)
    SELECT
        table_a_seq.NEXTVAL,
        b.name,
        123
    FROM
        table_b b;

Ergebnis:

ID: NAME: CODE:
1, JOHN, 123
2, SAM, 123
3, JESS, 123

usw

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.