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 le faire?
Comme BrianCampbell indique ici , SQLite 3.7.11 et les versions ultérieures prennent désormais en charge la syntaxe plus simple du message d'origine . Toutefois, l'approche indiquée reste appropriée si vous souhaitez une compatibilité maximale entre bases de données héritées.
Si j'avais des privilèges, je bumpais réponse d'Andy : Vous pouvez insérer plusieurs lignes dans SQLite, vous avez juste besoin de syntaxe différente . Pour que ce soit parfaitement clair, l'exemple MySQL des PO:
INSERT INTO 'tablename' ('column1', 'column2') VALUES
('data1', 'data2'),
('data1', 'data2'),
('data1', 'data2'),
('data1', 'data2');
Ceci peut être refait dans 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'
J'ai initialement utilisé cette technique pour charger efficacement de grands ensembles de données à partir de Ruby sur Rails. Cependant , comme le souligne Jaime Cook , il n’est pas clair qu’il soit plus rapide d’envelopper un individu INSERTs
dans un seul transaction:
BEGIN TRANSACTION;
INSERT INTO 'tablename' table VALUES ('data1', 'data2');
INSERT INTO 'tablename' table VALUES ('data3', 'data4');
...
COMMIT;
Si votre objectif est l'efficacité, essayez-le d'abord.
Comme plusieurs personnes l'ont commenté, si vous utilisez UNION ALL
(comme indiqué ci-dessus), toutes les lignes seront insérées. Dans ce cas, vous obtiendrez alors quatre lignes de data1, data2
. Si vous omettez le ALL
, les lignes en double seront éliminées (et l'opération sera probablement un peu plus lente). Nous utilisons UNION ALL car il correspond plus étroitement à la sémantique du message d'origine.
P.S .: S'il vous plaît +1 réponse d'Andy , pas la mienne! Il a présenté la solution en premier.
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, il est un peu moche mais assez facile d'automatiser la génération de l'instruction à partir d'un ensemble de valeurs. En outre, il apparaît que vous devez uniquement déclarer les noms de colonne dans la première sélection.
Oui, à partir de SQLite .7.11 ceci est supporté dans SQLite. De la documentation SQLite :
(lorsque cette réponse a été écrite à l'origine, cela n'était pas supporté)
Pour assurer la compatibilité avec les anciennes versions de SQLite, vous pouvez utiliser l’astuce suggérée par andy et fearless_fool en utilisant UNION
, mais pour 3.7.11 et les versions ultérieures, la syntaxe plus simple décrite dans ici devrait être préféré.
J'ai écrit du code Ruby pour générer une insertion d'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 simplement essayé de regrouper les multiples insertions dans une seule transaction et de constater que je pouvais atteindre le même type de vitesse avec beaucoup moins de code.
BEGIN TRANSACTION;
INSERT INTO table VALUES (1,1,1,1);
INSERT INTO table VALUES (2,2,2,2);
...
COMMIT;
Selon cette page ce n'est pas supporté:
- 2007-12-03: INSERT à plusieurs rangées a.k.a composé INSERT non pris en charge.
INSERT INTO table (col1, col2) VALUES
('row1col1', 'row1col2'), ('row2col1', 'row2col2'), ...
En fait, selon le standard SQL92, une expression VALUES devrait 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';
A partir de la version 3.7.11, SQLite prend en charge multi-row-insert . Richard Hipp a commenté:
"La nouvelle insertion à valeurs multiples est simplement une syntaxe syntaxique (sic) pour l'insertion composée. Il n'y a aucun avantage en termes de performances d'une manière ou d'une autre."
Depuis 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: S'il vous plaît +1 à la réponse/réponse de Brian Campbell. pas le mien! Il a présenté la solution en premier.
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 le seul moyen d'insérer plusieurs lignes est d'utiliser une instruction select comme source des données être inséré.
Comme l'ont dit d'autres afficheurs, SQLite ne prend pas en charge cette syntaxe. Je ne sais pas si les INSERT composés font partie du standard SQL, mais d'après mon expérience, ils sont non implémentés dans de nombreux produits.
Soit dit 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.
Sqlite3 ne peut le faire directement en SQL que via un SELECT, et alors que SELECT peut renvoyer une "rangée" d'expressions, je ne connais aucun moyen de lui faire renvoyer une colonne factice.
Cependant, le 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 placez une boucle autour d'un INSERT plutôt que d'utiliser la commande CLI .import
, veillez à suivre les conseils donnés dans sqlite FAQ pour la vitesse INSERT:
Par défaut, chaque instruction INSERT est sa propre transaction. Mais si vous entourez plusieurs instructions INSERT avec BEGIN ... COMMIT, toutes les insertions sont regroupées dans une seule transaction. Le temps nécessaire pour valider la transaction est amorti sur toutes les instructions insert incluses, ce qui permet de réduire considérablement l’instruction time par insert.
Une autre option consiste à exécuter PRAGMA synchrone = OFF. Grâce à cette commande, SQLite n'attendra pas que les données atteignent la surface du disque, ce qui rendra les opérations d'écriture plus rapides. Mais si vous perdez le pouvoir au milieu d'une transaction, votre fichier de base de données peut être corrompu.
fearless_fool a une excellente réponse pour les anciennes versions. Je voulais juste ajouter que vous devez vous assurer que toutes les colonnes sont répertoriées. Donc, si vous avez 3 colonnes, vous devez vous assurer que select agit sur 3 colonnes.
Exemple: J'ai 3 colonnes mais je veux seulement insérer 2 colonnes de données. Supposons que je me fiche de la première colonne car il s'agit d'un identifiant entier standard. Je pourrais faire ce qui suit ...
INSERT INTO 'tablename'
SELECT NULL AS 'column1', 'data1' AS 'column2', 'data2' AS 'column3'
UNION SELECT NULL, 'data3', 'data4'
UNION SELECT NULL, 'data5', 'data6'
UNION SELECT NULL, 'data7', 'data8'
Remarque: N'oubliez pas que l'instruction "select ... union" perd la commande. (De AG1)
Alex a raison: la déclaration "select ... union" perd 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, préférez donc utiliser des transactions si la commande d'insertion est importante.
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
INSERT INTO TABLE_NAME
(DATA1,
DATA2)
VALUES (VAL1,
VAL2),
(VAL1,
VAL2),
(VAL1,
VAL2),
(VAL1,
VAL2),
(VAL1,
VAL2),
(VAL1,
VAL2),
(VAL1,
VAL2),
(VAL1,
VAL2);
dans mysql lite, vous ne pouvez pas insérer plusieurs valeurs, mais vous pouvez gagner du temps en ouvrant la connexion une seule fois, puis en effectuant toutes les insertions, puis en fermant la connexion. Ça fait gagner beaucoup de temps
Vous ne pouvez pas mais je ne pense pas que rien ne vous manque.
Comme vous appelez toujours sqlite dans le processus, peu importe la performance, que vous exécutiez une instruction insert ou 100 instructions insert. Cependant, le commit prend beaucoup de temps, alors mettez ces 100 insertions dans une transaction.
Sqlite est beaucoup plus rapide lorsque vous utilisez des requêtes paramétrées (beaucoup moins d’analyses nécessaires), donc je ne concaténerais pas de grandes instructions comme celle-ci:
insert into mytable (col1, col2)
select 'a','b'
union
select 'c','d'
union ...
Ils doivent être analysés encore et encore, car chaque déclaration concaténée est différente.
Le problème de l'utilisation de transaction est que vous verrouillez également la table en lecture. Donc, si vous avez vraiment beaucoup de données à insérer et que vous devez accéder à vos données, par exemple un aperçu ou autre, cette méthode ne fonctionne pas bien.
Le problème avec l’autre solution est que vous perdez l’ordre d’insertion.
insert into mytable (col)
select 'c'
union
select 'd'
union
select 'a'
union
select 'b';
Dans le sqlite, les données seront stockées a, b, c, d ...
A partir de la version 3.7.11, SQLite prend en charge l’insertion sur plusieurs lignes. Richard Hipp a commenté:
J'utilise 3.6.13
Je commande comme ça:
insert into xtable(f1,f2,f3) select v1 as f1, v2 as f2, v3 as f3
union select nextV1+, nextV2+, nextV3+
Avec 50 enregistrements insérés à la fois, cela ne prend qu'une seconde ou moins.
C'est vrai d'utiliser sqlite pour insérer plusieurs lignes à la fois, c'est très possible. Par @Andy a écrit.
merci Andy +1
INSERT INTO tabela(coluna1,coluna2)
SELECT 'texto','outro'
UNION ALL
SELECT 'mais texto','novo texto';
J'ai une requête comme ci-dessous, mais avec ODBC, le pilote SQLite a une erreur avec "," il est écrit. Je lance vbscript dans HTA (application HTML).
INSERT INTO evrak_ilac_iliskileri (evrak_id, ilac_id, baglayan_kullanici_id, tarih) VALUES (4150,762,1,datetime()),(4150,9770,1,datetime()),(4150,6609,1,datetime()),(4150,3628,1,datetime()),(4150,9422,1,datetime())
Je suis capable de rendre la requête dynamique. Ceci est ma table:
CREATE TABLE "tblPlanner" ("probid" text,"userid" TEXT,"selectedtime" DATETIME,"plannerid" TEXT,"isLocal" BOOL,"applicationid" TEXT, "comment" TEXT, "subject" TEXT)
et je reçois toutes les données à travers un JSON
, donc après avoir tout contenu dans un NSArray
j'ai suivi ceci:
NSMutableString *query = [[NSMutableString alloc]init];
for (int i = 0; i < arr.count; i++)
{
NSString *sqlQuery = nil;
sqlQuery = [NSString stringWithFormat:@" ('%@', '%@', '%@', '%@', '%@', '%@', '%@', '%@'),",
[[arr objectAtIndex:i] objectForKey:@"plannerid"],
[[arr objectAtIndex:i] objectForKey:@"probid"],
[[arr objectAtIndex:i] objectForKey:@"userid"],
[[arr objectAtIndex:i] objectForKey:@"selectedtime"],
[[arr objectAtIndex:i] objectForKey:@"isLocal"],
[[arr objectAtIndex:i] objectForKey:@"subject"],
[[arr objectAtIndex:i] objectForKey:@"comment"],
[[NSUserDefaults standardUserDefaults] objectForKey:@"applicationid"]
];
[query appendString:sqlQuery];
}
// REMOVING LAST COMMA NOW
[query deleteCharactersInRange:NSMakeRange([query length]-1, 1)];
query = [NSString stringWithFormat:@"insert into tblPlanner (plannerid, probid, userid, selectedtime, isLocal, applicationid, subject, comment) values%@",query];
Et enfin, la requête de sortie est la suivante:
insert into tblPlanner (plannerid, probid, userid, selectedtime, isLocal, applicationid, subject, comment) values
<append 1>
('pl1176428260', '', 'US32552', '2013-06-08 12:00:44 +0000', '0', 'subj', 'Hiss', 'ap19788'),
<append 2>
('pl2050411638', '', 'US32552', '2013-05-20 10:45:55 +0000', '0', 'TERI', 'Yahoooooooooo', 'ap19788'),
<append 3>
('pl1828600651', '', 'US32552', '2013-05-21 11:33:33 +0000', '0', 'test', 'Yest', 'ap19788'),
<append 4>
('pl549085534', '', 'US32552', '2013-05-19 11:45:04 +0000', '0', 'subj', 'Comment', 'ap19788'),
<append 5>
('pl665538927', '', 'US32552', '2013-05-29 11:45:41 +0000', '0', 'subj', '1234567890', 'ap19788'),
<append 6>
('pl1969438050', '', 'US32552', '2013-06-01 12:00:18 +0000', '0', 'subj', 'Cmt', 'ap19788'),
<append 7>
('pl672204050', '', 'US55240280', '2013-05-23 12:15:58 +0000', '0', 'aassdd', 'Cmt', 'ap19788'),
<append 8>
('pl1019026150', '', 'US32552', '2013-06-08 12:15:54 +0000', '0', 'exists', 'Cmt', 'ap19788'),
<append 9>
('pl790670523', '', 'US55240280', '2013-05-26 12:30:21 +0000', '0', 'qwerty', 'Cmt', 'ap19788')
qui fonctionne bien aussi avec le code et je suis capable de tout sauvegarder dans SQLite avec succès.
Avant cela, j’ai rendu la requête UNION
dynamique, mais cela a commencé à donner une erreur de syntaxe. Quoi qu'il en soit, cela fonctionne bien pour moi.
Si vous utilisez le plugin Sqlite manager firefox, il prend en charge les insertions en bloc à partir d'instructions INSERT
SQL.
Enfait, il ne supporte pas cela, mais Sqlite Browser le fait (fonctionne sous Windows, OS X, Linux)
Sur sqlite 3.7.2:
INSERT INTO table_name (column1, column2)
SELECT 'value1', 'value1'
UNION SELECT 'value2', 'value2'
UNION SELECT 'value3', 'value3'
etc
Je suis surpris que personne n'ait mentionné déclarations préparées. À moins que vous n'utilisiez SQL seul et pas dans une autre langue, alors je penserais que instructions préparées enveloppé dans un transaction serait le moyen le plus efficace d'insérer plusieurs lignes .
vous pouvez utiliser InsertHelper, c'est facile et rapide
documentation: http://developer.Android.com/reference/Android/database/DatabaseUtils.InsertHelper.html
Edit: InsertHelper est obsolète à partir du niveau 17 de l'API