348 votes

Meilleur moyen d'insérer plusieurs rangs dans Oracle ?

Je cherche un bon moyen d'effectuer des insertions sur plusieurs lignes dans une base de données Oracle 9. La méthode suivante fonctionne dans MySQL mais ne semble pas être prise en charge par 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');

460voto

Myto Points 869

Dans Oracle, pour insérer plusieurs lignes dans la table t avec les 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;

82 votes

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

4 votes

Selon cette page de tutoriel , SELECT * FROM DUAL fonctionne aussi.

1 votes

@jameshfisher Je ne sais pas pourquoi l'insertion multiple requiert la sélection de DUAL mais je peux vous dire que DUAL est : un tableau prédéfini . Exécuter SELECT * FROM DUAL pour le visualiser.

212voto

Espo Points 24318

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 le from dual déclaration.

( source )

9 votes

Il existe également une fonction appelée "Insert All" depuis la version 9i( ?).

5 votes

Je suis pointilleux, mais la mise en forme est plus logique si vous mettez "union all" à la fin de chaque ligne de sélection (sauf la dernière).

5 votes

L'inconvénient de cette méthode est que nous ne pouvons pas utiliser un système d'alerte. sequnce.nextval car elle est interdite dans union de select . Au lieu de cela, nous pouvons aller avec INSERT ALL .

35voto

Matthew Watson Points 7762

Utilisez SQL*Loader. Cela demande un peu d'organisation, mais si ce n'est pas un cas isolé, cela en vaut la peine.

Créer une table

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

Créer un CSV

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

Créer le fichier de contrôle du chargeur

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 la commande 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

Confirmer l'insertion

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 n'importe quel fichier texte comme 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 supplémentaires -> SQL*Loader

0 votes

La colonne ID de mon tableau est autogénérée. Puis-je simplement ignorer le champ ID dans le fichier de contrôle du chargeur ?

0 votes

@Thom, utilisez la séquence.nextval par exemple. fruit_id "fruit_seq.nextval" dans la définition de la colonne

0 votes

50 millions d'enregistrements en quelques minutes. La voie à suivre

27voto

Chaque fois que j'ai besoin de faire cela, je construis un bloc PL/SQL simple avec une procédure locale comme ceci :

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

0 votes

Cette réponse fonctionne très bien, surtout si vous devez utiliser des séquences. Upvoted.

14voto

Ryan Ahearn Points 3829

Si vous avez déjà les valeurs que vous voulez insérer dans une autre table, vous pouvez insérer à partir d'une instruction de sélection.

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

Sinon, vous pouvez dresser une liste d'instructions d'insertion à une seule ligne et soumettre plusieurs requêtes en vrac pour gagner du temps et obtenir quelque chose qui fonctionne à la fois dans Oracle et MySQL.

@Espo La solution de l'auteur est également une bonne solution qui fonctionne à la fois avec Oracle et MySQL si vos données ne sont pas déjà dans une table.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X