Question Est-il possible d'insérer plusieurs lignes à la fois dans une base de données SQLite?


Dans MySQL, vous pouvez insérer plusieurs lignes comme ceci:

INSERT INTO 'tablename' ('column1', 'column2') VALUES
    ('data1', 'data2'),
    ('data1', 'data2'),
    ('data1', 'data2'),
    ('data1', 'data2');

Cependant, je reçois une erreur lorsque j'essaie de faire quelque chose comme ça. Est-il possible d'insérer plusieurs lignes à la fois dans une base de données SQLite? Quelle est la syntaxe pour faire cela?


482
2017-10-22 20:04


origine


Réponses:


mettre à jour

Comme BrianCampbell fait remarquer ici, SQLite 3.7.11 et supérieur prend désormais en charge la syntaxe plus simple du message original. Toutefois, l'approche indiquée est toujours appropriée si vous souhaitez une compatibilité maximale entre les bases de données existantes.

réponse originale

Si j'avais des privilèges, je cognerais la réponse d'andy: Toi pouvez insérer plusieurs lignes dans SQLite, il vous suffit de syntaxe différente. Pour que ce soit parfaitement clair, l’exemple des OPs MySQL:

INSERT INTO 'tablename' ('column1', 'column2') VALUES
  ('data1', 'data2'),
  ('data1', 'data2'),
  ('data1', 'data2'),
  ('data1', 'data2');

Cela peut être refondu en SQLite comme:

     INSERT INTO 'tablename'
          SELECT 'data1' AS 'column1', 'data2' AS 'column2'
UNION ALL SELECT 'data1', 'data2'
UNION ALL SELECT 'data1', 'data2'
UNION ALL SELECT 'data1', 'data2'

une note sur la performance

J'ai d'abord utilisé cette technique pour charger efficacement de grands ensembles de données à partir de Ruby on Rails. toutefois, comme le souligne Jaime Cook, il n'est pas clair que ce soit un emballage plus rapide INSERTs en une seule transaction:

BEGIN TRANSACTION;
INSERT INTO 'tablename' table VALUES ('data1', 'data2');
INSERT INTO 'tablename' table VALUES ('data3', 'data4');
...
COMMIT;

Si l'efficacité est votre objectif, vous devriez d'abord essayer.

une note sur UNION vs UNION ALL

Comme plusieurs personnes ont commenté, si vous utilisez UNION ALL (comme indiqué ci-dessus), toutes les lignes seront insérées, donc dans ce cas, vous obtiendrez quatre lignes de data1, data2. Si vous omettez le ALL, alors les lignes dupliquées seront éliminées (et l'opération sera vraisemblablement un peu plus lente). Nous utilisons UNION ALL car il correspond plus étroitement à la sémantique du message original.

en fermeture

P.S .: S'il vous plaît +1 la réponse d'andy, pas le mien! Il a présenté la solution en premier.


556
2018-02-15 21:29



Oui c'est possible, mais pas avec les valeurs d'insertion habituelles séparées par des virgules.

Essaye ça...

insert into myTable (col1,col2) 
     select aValue as col1,anotherValue as col2 
     union select moreValue,evenMoreValue 
     union...

Oui, c'est un peu moche mais assez facile d'automatiser la génération de la déclaration à partir d'un ensemble de valeurs. En outre, il semble que vous ayez seulement besoin de déclarer les noms des colonnes dans la première sélection.


527
2017-11-14 12:06



Oui, à partir de SQLite 3.7.11 ceci est supporté dans SQLite. Du Documentation SQLite:

SQLite INSERT statement syntax

(quand cette réponse a été écrite à l'origine, ce n'était pas supporté)

Pour la compatibilité avec les anciennes versions de SQLite, vous pouvez utiliser l'astuce proposée par Andy et fearless_fool en utilisant UNION, mais pour 3.7.11 et plus tard, la syntaxe plus simple décrite ici devrait être préférée.


221
2017-10-22 20:13



J'ai écrit du code ruby ​​pour générer un insert à plusieurs lignes de 500 éléments à partir d'une série d'instructions d'insertion, ce qui était considérablement plus rapide que l'exécution des insertions individuelles. Ensuite, j'ai essayé simplement d'encapsuler les multiples insertions dans une seule transaction et j'ai découvert que je pouvais obtenir le même type d'accélération avec beaucoup moins de code.

BEGIN TRANSACTION;
INSERT INTO table VALUES (1,1,1,1);
INSERT INTO table VALUES (2,2,2,2);
...
COMMIT;

52
2018-03-06 06:26



Selon cette page il n'est pas supporté:

  • 2007-12-03: INSERT à plusieurs lignes INSERT a.k.a composé non pris en charge.
  INSERT INTO table (col1, col2) VALUES 
      ('row1col1', 'row1col2'), ('row2col1', 'row2col2'), ...

En fait, selon le standard SQL92, une expression VALUES doit pouvoir se tenir sur elle-même. Par exemple, les éléments suivants doivent renvoyer une table à une colonne avec trois lignes: VALUES 'john', 'mary', 'paul';

À partir de la version 3.7.11 SQLite Est-ce que soutien multi-rangée-insert. Richard Hipp commente:

"Le nouvel insert à valeurs multiples est simplement suger syntaxique (sic) pour le composé   insérer. Il n'y a pas d'avantage de performance dans un sens ou dans l'autre. "


37
2017-10-22 20:15



À partir de la version 2012-03-20 (3.7.11), sqlite prend en charge la syntaxe INSERT suivante:

INSERT INTO 'tablename' ('column1', 'column2') VALUES
  ('data1', 'data2'),
  ('data3', 'data4'),
  ('data5', 'data6'),
  ('data7', 'data8');

Lire la documentation: http://www.sqlite.org/lang_insert.html

PS: Veuillez +1 à la réponse / réponse de Brian Campbell. pas le mien! Il a présenté la solution en premier.


11
2018-05-16 16:07



Comme l'ont dit les autres affiches, SQLite ne supporte pas cette syntaxe. Je ne sais pas si les INSERTs composés font partie de la norme SQL, mais dans mon expérience, ils sont ne pas mis en œuvre dans de nombreux produits.

En passant, vous devez savoir que les performances INSERT dans SQLite sont considérablement améliorées si vous encapsulez plusieurs INSERT dans une transaction explicite.


10
2017-11-14 12:21



Oui, SQL peut le faire, mais avec une syntaxe différente. le Documentation sqlite est plutôt bon, au fait. Il vous dira aussi que la seule façon d'insérer plusieurs lignes est utiliser une instruction select comme source des données à insérer.


10
2017-10-22 20:13



Sqlite3 ne peut pas le faire directement en SQL, sauf via SELECT, et alors que SELECT peut renvoyer une "ligne" d’expressions, je ne sais pas comment le faire renvoyer une colonne bidon.

Cependant, la CLI peut le faire:

.import FILE TABLE     Import data from FILE into TABLE
.separator STRING      Change separator used by output mode and .import

$ sqlite3 /tmp/test.db
SQLite version 3.5.9
Enter ".help" for instructions
sqlite> create table abc (a);
sqlite> .import /dev/tty abc
1
2
3
99
^D
sqlite> select * from abc;
1
2
3
99
sqlite> 

Si vous mettez une boucle autour d'un INSERT, plutôt que d'utiliser l'interface CLI .import commande, puis assurez-vous de suivre les conseils de la FAQ sqlite pour INSERT speed:

Par défaut, chaque instruction INSERT est   sa propre transaction. Mais si tu   entourer plusieurs instructions INSERT   avec BEGIN ... COMMIT alors tous les   les insertions sont regroupées dans un seul   transaction. Le temps nécessaire pour s'engager   la transaction est amortie sur tous   les insertions ci-jointes et ainsi   le temps par instruction d'insertion est   grandement réduit.

Une autre option est de lancer PRAGMA   synchrone = OFF. Cette commande va   SQLite ne pas attendre sur les données pour   atteindre la surface du disque, ce qui va   faire des opérations d'écriture semblent être   Plus vite. Mais si vous perdez de la puissance   au milieu d'une transaction, votre   fichier de base de données peut être corrompu.


8
2017-10-22 20:22



Alex a raison: la déclaration "select ... union" perdra la commande, ce qui est très important pour certains utilisateurs. Même lorsque vous insérez dans un ordre spécifique, sqlite change les choses de sorte qu'il est préférable d'utiliser des transactions si l'ordre d'insertion est important.

create table t_example (qid int not null, primary key (qid));
begin transaction;
insert into "t_example" (qid) values (8);
insert into "t_example" (qid) values (4);
insert into "t_example" (qid) values (9);
end transaction;    

select rowid,* from t_example;
1|8
2|4
3|9

7
2018-06-19 07:11