Oracle'da çok satırlı ekleme yapmanın en iyi yolu?


262

Bir Oracle 9 veritabanına çok satırlı ekler gerçekleştirmek için iyi bir yol arıyorum. Aşağıdakiler MySQL'de çalışır, ancak Oracle'da desteklenmiyor gibi görünür.

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');

Yanıtlar:


165

Oracle'da şu şekilde çalışır:

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

Burada hatırlanması gereken şey from dual ifadeyi .

( kaynak )


6
Ayrıca 9i (?)
İtibarıyla

4
Seçici olmakla birlikte, her seçim satırının sonuna (sonuncusu hariç) "birliği" koyarsanız biçimlendirme daha anlamlı olur.
Jamie

Bu bir dezavantajı biz cant'kullanma olduğu sequnce.nextvalo yasaklanmıştır olarak unionbir select. Bunun yerine gidebiliriz INSERT ALL.
sql_dummy

5
@Jamie: Espo'nun biçimlendirilmesi, yeni satır eklerken son satırda olup olmadığınız konusunda endişelenmeniz gerekmediği için biraz daha akıllıdır. Bu nedenle, ilk 2 seçiminizi yaptıktan sonra, yalnızca değiştirmek zorunda olduğunuz değerlere odaklanarak son satırı (veya ortadaki) kolayca kopyalayıp yapıştırabilirsiniz. Herhangi bir dilde (virgül, mantık operatörleri, artı ...) diğer birçok durum için ortak bir numaradır. Bu sadece bir alışkanlık meselesi, kodun sorumluluğuna sezgisellikten daha fazla odaklanmak için birçok eski uygulama revize edildi.
Laurent.B

12c için maksimum değer nedir?
Alet

363

Oracle'da, col1, col2 ve col3 sütunlarıyla tablo t'a birden çok satır eklemek için aşağıdaki sözdizimini kullanabilirsiniz:

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
Ne yaptığını anlamıyorum SELECT 1 FROM DUAL.
jameshfisher

55
INSERT ALLbir SELECTalt sorgu gerektirir . Bunu aşmak için, SELECT 1 FROM DUALtek bir satır kukla veri vermek için kullanılır.
Markus Jarderot

40
Bu, birden çok ekleme ifadesinden nasıl farklıdır? Hala sütun isimleri üzerinde tekrar var, bu yüzden çok fazla kazanma gibi görünmüyor.
Burhan Ali

28
Yukarıdaki sözdizimi saniyede 1000 kayıt ekleyebilirken, yaklaşık 10-12 Birden fazla INSERT ifadesi bilgisayarımdaki 2 saniyede tamamlanır! Etkilenen! Ben sadece sonunda TAAHHÜT olduğunu unutmayın.
Kent Pawar

13
Bu iyi çalışır, ancak bir sıra kullanarak ekliyorsanız, user.NEXTVAL her kesici uç için aynı değeri döndürür. Tümü insertin içinde manuel olarak artırabilir, ardından sekansı insertin dışında güncelleyebilirsiniz.
user1412523

33

SQL * Loader kullanın. Biraz kurulum gerektiriyor, ancak bu bir tane değilse, buna değer.

Tablo Oluştur

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

CSV oluştur

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

Yükleyici Denetim Dosyası Oluştur

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% 

SQL * Loader komutunu çalıştırın

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

Eklemeyi onayla

SQL> select * from ldr_test;

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

SQL>

SQL * Loader birçok seçeneğe sahiptir ve giriş olarak hemen hemen her metin dosyasını alabilir. İsterseniz, kontrol dosyanızdaki verileri hatta satır içine alabilirsiniz.

İşte biraz daha ayrıntı içeren bir sayfa -> SQL * Yükleyici


Bu en büyük cevap IMHO olmalı, başka bir şey (büyük ölçekli görevler için) sorun istiyor
roblogic

Tablomdaki kimlik sütunu otomatik olarak oluşturulur. Yükleyici kontrol dosyasındaki kimlik alanını atlayabilir miyim?
Thom DeCarlo

@Thom, örneğin fruit_id "fruit_seq.nextval"sütun tanımında sırayı.nextval kullanın
roblogic

Birkaç dakika içinde 50 milyon kayıt.
Toolkit

20

Ne zaman bunu yapmak gerektiğinde ben böyle bir yerel prosedür ile basit bir PL / SQL bloğu inşa:

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

Zaten başka bir tabloya eklemek istediğiniz değerlere sahipseniz, select deyiminden ekleyebilirsiniz.

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

Aksi takdirde, hem Oracle hem de MySQL'de çalışan bir şeyin zamanından tasarruf etmek için bir grup tek satırlı ekleme ifadesi listeleyebilir ve toplu olarak birkaç sorgu gönderebilirsiniz.

@Espo'nun çözümü, verileriniz zaten bir tabloda değilse, hem Oracle hem de MySQL'de çalışacak iyi bir çözümdür.


4

bazı rastgele değerler eklemek istiyorsanız döngü kullanarak ekleyebilirsiniz.

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


0

Oracle'da birden çok satır eklemek için çok kullanışlı bir adım adım kılavuz:

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

Son adım:

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

Benim durumumda, TABLE_B sadece bir sütun kullanarak ve başka bir yerde (dizi ve sabit kodlanmış bir değer) elde TABLE_A içine birçok satır toplu eklemek için basit bir ekleme deyimi kullanabildi:

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

Sonuç:

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

vb

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.