Cách tốt nhất để chèn nhiều hàng trong Oracle?


262

Tôi đang tìm kiếm một cách tốt để thực hiện chèn nhiều hàng vào cơ sở dữ liệu Oracle 9. Các hoạt động sau đây trong MySQL nhưng dường như không được hỗ trợ trong Oracle.

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

Câu trả lời:


165

Điều này hoạt động trong 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

Điều cần nhớ ở đây là sử dụng from dualcâu lệnh.

( nguồn )


6
Ngoài ra còn có một thứ gọi là "Chèn tất cả" kể từ 9i (?)
mledit

4
Rất kén chọn, nhưng định dạng sẽ có ý nghĩa hơn nếu bạn đặt "union all" ở cuối mỗi dòng chọn (ngoại trừ dòng cuối cùng).
Jamie

Một bất lợi với điều này là chúng ta không thể sử dụng một sequnce.nextvalkhi nó bị cấm trong unioncác select. Thay vào đó chúng ta có thể đi với INSERT ALL.
sql_dummy

5
@Jamie: định dạng của Espo thông minh hơn một chút theo nghĩa bạn không phải lo lắng về việc bạn có ở dòng cuối cùng hay không, khi thêm dòng mới. Do đó, khi bạn có 2 lựa chọn đầu tiên, bạn có thể dễ dàng sao chép / dán dòng cuối cùng (hoặc một dòng giữa), chỉ tập trung vào các giá trị mà bạn phải thay đổi. Đây là một mẹo phổ biến cho nhiều trường hợp khác trong bất kỳ ngôn ngữ nào (dấu phẩy, toán tử logic, cộng với ...). Đó chỉ là vấn đề của thói quen, rất nhiều thực tiễn trước đây đã được sửa đổi để tập trung vào trách nhiệm của mã hơn là trực giác.
Laurent.B

tối đa cho 12c là bao nhiêu?
Bộ công cụ

363

Trong Oracle, để chèn nhiều hàng vào bảng t với các cột col1, col2 và col3, bạn có thể sử dụng cú pháp sau:

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
Tôi không hiểu những gì SELECT 1 FROM DUAL.
jameshfisher

55
INSERT ALLđòi hỏi một SELECTtruy vấn con Để giải quyết vấn đề đó, SELECT 1 FROM DUALđược sử dụng để đưa ra một hàng dữ liệu giả.
Markus Jarderot

40
Điều này khác với nhiều câu lệnh chèn như thế nào? Bạn vẫn có sự lặp lại trên các tên cột vì vậy dường như không thu được nhiều.
Burhan Ali

28
Khoảng 10-12 Nhiều câu lệnh INSERT được hoàn thành trong 2 giây trên PC của tôi, trong khi cú pháp trên có thể CHỈ 1000 bản ghi mỗi giây! Ấn tượng! Lưu ý rằng tôi CAM KẾT chỉ ở cuối.
Kent Pawar

13
Điều này hoạt động tốt, tuy nhiên nếu bạn đang chèn bằng một chuỗi, giả sử người dùng.NEXTVAL, nó sẽ trả về cùng một giá trị cho mỗi lần chèn. Bạn có thể tự tăng nó trong phần chèn tất cả, sau đó cập nhật trình tự bên ngoài phần chèn.
dùng1412523

33

Sử dụng SQL * Trình tải. Nó cần một chút thiết lập, nhưng nếu đây không phải là một thiết bị tắt, nó đáng giá.

Tạo bảng

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

Tạo CSV

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

Tạo tập tin điều khiển bộ tải

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% 

Chạy lệnh SQL * Loader

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

Xác nhận chèn

SQL> select * from ldr_test;

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

SQL>

SQL * Loader có rất nhiều tùy chọn và có thể lấy khá nhiều tệp văn bản làm đầu vào. Bạn thậm chí có thể nội tuyến dữ liệu trong tệp điều khiển của bạn nếu bạn muốn.

Đây là một trang có thêm một số chi tiết -> SQL * Loader


Đây phải là câu trả lời hàng đầu IMHO, bất cứ điều gì khác (đối với các nhiệm vụ quy mô lớn) đang yêu cầu sự cố
roblogic

Cột ID trong bảng của tôi được tự động tạo. Tôi có thể chỉ cần bỏ qua trường ID trong tệp điều khiển trình tải không?
Thom DeCarlo

@Thom, sử dụng chuỗi.nextval, ví dụ: fruit_id "fruit_seq.nextval"trong định nghĩa cột
roblogic

50 triệu hồ sơ trong vài phút. Con đường để đi
Bộ công cụ

20

Bất cứ khi nào tôi cần làm điều này, tôi xây dựng một khối PL / SQL đơn giản với một thủ tục cục bộ như thế này:

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

Nếu bạn đã có các giá trị mà bạn muốn chèn vào một bảng khác, thì bạn có thể Chèn từ một câu lệnh chọn.

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

Mặt khác, bạn có thể liệt kê một loạt các câu lệnh chèn một hàng và gửi một số truy vấn hàng loạt để tiết kiệm thời gian cho một cái gì đó hoạt động trong cả Oracle và MySQL.

Giải pháp của @Espo cũng là một giải pháp tốt sẽ hoạt động trong cả Oracle và MySQL nếu dữ liệu của bạn chưa có trong một bảng.


4

bạn có thể chèn bằng vòng lặp nếu bạn muốn chèn một số giá trị ngẫu nhiên.

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


0

Dưới đây là hướng dẫn từng bước rất hữu ích để chèn nhiều hàng trong Oracle:

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

Bước cuối cùng:

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

Trong trường hợp của tôi, tôi đã có thể sử dụng một câu lệnh chèn đơn giản để chèn hàng loạt nhiều hàng vào TABLE_A chỉ bằng một cột từ TABLE_B và nhận dữ liệu khác ở nơi khác (chuỗi và giá trị được mã hóa cứng):

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

Kết quả:

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

Vân vân

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.