2008-09-02 7 views
175

Je cherche un bon moyen d'effectuer des insertions à plusieurs lignes dans une base de données Oracle 9. Ce qui suit fonctionne dans MySQL mais ne semble pas être supporté par Oracle.La meilleure façon de faire une insertion à plusieurs lignes dans 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'); 

Répondre

108

Cela fonctionne dans 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 

La chose à retenir ici est d'utiliser la déclaration from dual.

(source)

+4

Il y a aussi quelque chose appelé « Tout insérer » au 9i – mlathe

+0

Être pointilleux, mais le formatage a plus de sens si vous mettez "union all" à la fin de chaque ligne de sélection (sauf pour le dernier). – Jamie

+0

Un inconvénient avec ceci est que nous ne pouvons pas utiliser une 'séquence.nextval' comme il est interdit dans 'union'of' select'. Au lieu de cela, nous pouvons aller avec 'INSERT ALL'. –

10

Si vous avez les valeurs que vous souhaitez insérer dans une autre table déjà, vous pouvez insérer à partir d'une instruction select.

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

Sinon, vous pouvez lister un tas de déclarations insérer une seule rangée et soumettre plusieurs requêtes en vrac pour sauver le temps pour quelque chose qui fonctionne à la fois Oracle et MySQL.

La solution de @Espo est également une bonne solution qui fonctionnera dans Oracle et MySQL si vos données ne sont pas déjà dans une table.

28

Utilisez SQL * Loader. Cela prend un peu de mise en place, mais si ce n'est pas une fois, ça vaut le coup.

Créer une table

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

Créer CSV

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

Créer Loader fichier de contrôle

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% 

Exécuter SQL * commande du chargeur

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 

Confirmer insérer

SQL> select * from ldr_test; 

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

SQL> 

SQL * Loader a beaucoup d'options, et peut prendre à peu près tout fichier texte en entrée. Vous pouvez même intégrer les données dans votre fichier de contrôle si vous le souhaitez.

Voici une page avec quelques détails ->SQL*Loader

+0

Cela devrait être la meilleure réponse à mon avis, quoi que ce soit d'autre (pour les tâches de grande envergure) demande des problèmes – ropata

+0

La colonne ID de ma table est générée automatiquement. Puis-je simplement ignorer le champ ID dans le fichier de contrôle du chargeur? –

+0

@Thom, utilisez la séquence.nextval. 'fruit_id" fruit_seq.nextval "' dans la définition de colonne – ropata

19

Chaque fois que je dois faire ce que je construire simple bloc PL/SQL avec une procédure locale comme celui-ci:

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

Dans Oracle, pour insérer plusieurs lignes dans la table t avec des colonnes col1, col2 et col3 vous pouvez utiliser la syntaxe suivante: (?)

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

Je ne comprends pas ce que fait 'SELECT 1 FROM DUAL'. – jameshfisher

+2

Selon [cette page de tutoriel] (http://www.techonthenet.com/sql/insert.php), 'SELECT * FROM DUAL' fonctionne aussi. –

+0

@jameshfisher Je ne sais pas pourquoi l'insertion multiple nécessite la sélection de 'DUAL', mais je peux vous dire ce que' DUAL' est: [une table prédéfinie] (http://en.wikipedia.org/wiki/DUAL_table). Exécutez 'SELECT * FROM DUAL' pour l'afficher. –

Questions connexes