2008-09-02 40 views
175

Estoy buscando una buena manera de realizar inserciones de varias filas en una base de datos Oracle 9. Lo siguiente funciona en MySQL pero no parece ser compatible con Oracle.¿La mejor manera de insertar varias filas en 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'); 

Respuesta

108

Esto funciona en 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 

Lo que hay que recordar aquí es utilizar la instrucción from dual.

(source)

+4

también hay algo que se llama "insertar Todo" a partir de 9i – mlathe

+0

Ser quisquilloso, pero el formato tiene más sentido si coloca "union all" al final de cada línea de selección (excepto la última). – Jamie

+0

Una desventaja con esto es que no podemos usar un 'sequnce.nextval' como está prohibido en 'union'of' select'. En cambio, podemos ir con 'INSERT ALL '. –

10

Si usted tiene los valores que desea insertar en otra mesa ya, entonces puede insertar de una instrucción de selección.

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

De lo contrario, se puede enumerar un montón de instrucciones de inserción de una hilera y presentar varias consultas en grandes cantidades para ahorrar el tiempo para algo que funciona tanto en Oracle y MySQL.

@Espo es una buena solución que funcionará tanto en Oracle como en MySQL si sus datos aún no están en una tabla.

28

Use SQL * Loader. Se necesita un poco de configuración, pero si esto no es una sola vez, vale la pena.

crear tabla

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

Crear CSV

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

crear el archivo de control de la cargadora

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% 

Ejecutar SQL * Comando del cargador

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 

Confirmar insertar

SQL> select * from ldr_test; 

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

SQL> 

SQL * Loader tiene un montón de opciones, y puede tomar casi cualquier archivo de texto como su entrada. Incluso puede alinear los datos en su archivo de control si lo desea.

Aquí es una página con algunos detalles más ->SQL*Loader

+0

Esta debería ser la respuesta principal en mi humilde opinión, cualquier otra cosa (para tareas a gran escala) es pedir problemas – ropata

+0

La columna ID en mi tabla se autogenera. ¿Puedo simplemente omitir el campo ID en el archivo de control del cargador? –

+0

@Thom, use la secuencia.nextval p. Ej. 'fruit_id" fruit_seq.nextval "' en la definición de la columna – ropata

19

Cada vez que necesito para hacer esto construyo un simple bloque PL/SQL con un procedimiento local como esto:

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; 
/
263

En Oracle, insertar varias filas en la tabla T con columnas col1, col2 y col3 puede utilizar la siguiente sintaxis: (?)

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; 
+29

No entiendo qué hace 'SELECT 1 FROM DUAL'. – jameshfisher

+2

De acuerdo con [esta página de tutorial] (http://www.techonthenet.com/sql/insert.php), 'SELECT * FROM DUAL' también funciona. –

+0

@jameshfisher No sé por qué la inserción múltiple requiere la selección de 'DUAL', pero puedo decirle qué' DUAL' es: [una tabla predefinida] (http://en.wikipedia.org/wiki/DUAL_table). Ejecute 'SELECT * FROM DUAL' para verlo. –

Cuestiones relacionadas