una - tipos de datos sqlite android




¿Es posible insertar varias filas a la vez en una base de datos SQLite? (16)

En MySQL puedes insertar múltiples filas como esta:

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

Sin embargo, recibo un error cuando intento hacer algo como esto. ¿Es posible insertar varias filas a la vez en una base de datos SQLite? ¿Cuál es la sintaxis para hacer eso?


A partir de la versión 3.7.11, SQLite admite la inserción de varias filas. Richard Hipp comenta:

Estoy usando 3.6.13

Yo mando así:

insert into xtable(f1,f2,f3) select v1 as f1, v2 as f2, v3 as f3 
union select nextV1+, nextV2+, nextV3+

Con 50 registros insertados a la vez, solo toma un segundo o menos.

Es cierto que usar sqlite para insertar varias filas a la vez es muy posible. Por @Andy escribió.

gracias Andy +1


actualizar

Como señala BrianCampbell aquí , SQLite 3.7.11 y superior ahora admiten la sintaxis más simple de la publicación original . Sin embargo, el enfoque mostrado aún es apropiado si desea la máxima compatibilidad en las bases de datos heredadas.

respuesta original

Si tuviera privilegios, pondría la respuesta de Andy : puedes insertar varias filas en SQLite, solo necesitas una sintaxis diferente . Para que quede perfectamente claro, el ejemplo de OPs MySQL:

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

Esto puede ser refundido en SQLite como:

     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'

una nota sobre el rendimiento

Originalmente utilicé esta técnica para cargar de manera eficiente grandes conjuntos de datos de Ruby on Rails. Sin embargo , como apunta Jaime Cook , no está claro que esto sea más rápido para envolver INSERTs individuales dentro de una sola transacción:

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

Si la eficiencia es su objetivo, debe intentar esto primero.

una nota sobre UNION vs UNION ALL

Como varias personas comentaron, si usa UNION ALL (como se muestra arriba), todas las filas se insertarán, por lo que en este caso, obtendría cuatro filas de data1, data2 . Si omite el ALL , se eliminarán las filas duplicadas (y la operación probablemente será un poco más lenta). Estamos usando UNION ALL ya que coincide más con la semántica de la publicación original.

Para concluir

PD: Por favor, +1 respuesta de Andy , no mía! Presentó la solución primero.


Alex tiene razón: la declaración "seleccionar ... unión" perderá el orden, lo cual es muy importante para algunos usuarios. Incluso cuando inserta en un orden específico, sqlite cambia las cosas, así que prefiera usar transacciones si el pedido de inserciones es 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

Como han dicho los otros carteles, SQLite no admite esta sintaxis. No sé si los INSERT compuestos son parte del estándar SQL, pero en mi experiencia no están implementados en muchos productos.

Además, debe tener en cuenta que el rendimiento de INSERT en SQLite se mejora considerablemente si ajusta varios INSERT en una transacción explícita.


En sqlite 3.7.2:

INSERT INTO table_name (column1, column2) 
                SELECT 'value1', 'value1' 
          UNION SELECT 'value2', 'value2' 
          UNION SELECT 'value3', 'value3' 

y así


Escribí un código Ruby para generar una única inserción de múltiples filas de 500 elementos a partir de una serie de sentencias de inserción que fue considerablemente más rápida que ejecutar las inserciones individuales. Luego intenté simplemente envolver las inserciones múltiples en una sola transacción y descubrí que podía obtener el mismo tipo de aceleración con mucho menos código.

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

No puedes, pero no creo que te pierdas nada.

Debido a que llama a sqlite siempre en proceso, casi no importa en el rendimiento si ejecuta 1 instrucción de inserción o 100 instrucciones de inserción. Sin embargo, la confirmación lleva mucho tiempo, así que coloque esas 100 inserciones dentro de una transacción.

Sqlite es mucho más rápido cuando utilizas consultas parametrizadas (se necesita mucho menos análisis), por lo que no concatenaré grandes afirmaciones como esta:

insert into mytable (col1, col2)
select 'a','b'
union 
select 'c','d'
union ...

Deben analizarse una y otra vez porque cada declaración concatenada es diferente.



Sí, a partir de SQLite 3.7.11 esto es compatible con SQLite. De la documentación de SQLite :

(cuando esta respuesta fue escrita originalmente, esto no fue compatible)

Para la compatibilidad con versiones anteriores de SQLite, puede usar el truco sugerido por andy and fearless_fool usando UNION , pero para 3.7.11 y posteriores se debe preferir la sintaxis más simple descrita aquí.


Sí, es posible, pero no con los valores de inserción usuales separados por comas.

Prueba esto...

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

Sí, es un poco feo pero lo suficientemente fácil como para automatizar la generación de la declaración a partir de un conjunto de valores. Además, parece que solo necesita declarar los nombres de las columnas en la primera selección.


Si estás usando bash shell puedes usar esto:

time bash -c $'
FILE=/dev/shm/test.db
sqlite3 $FILE "create table if not exists tab(id int);"
sqlite3 $FILE "insert into tab values (1),(2)"
for i in 1 2 3 4; do sqlite3 $FILE "INSERT INTO tab (id) select (a.id+b.id+c.id)*abs(random()%1e7) from tab a, tab b, tab c limit 5e5"; done; 
sqlite3 $FILE "select count(*) from tab;"'

O si está en CLI de sqlite, entonces necesita hacer esto:

create table if not exists tab(id int);"
insert into tab values (1),(2);
INSERT INTO tab (id) select (a.id+b.id+c.id)*abs(random()%1e7) from tab a, tab b, tab c limit 5e5;
INSERT INTO tab (id) select (a.id+b.id+c.id)*abs(random()%1e7) from tab a, tab b, tab c limit 5e5;
INSERT INTO tab (id) select (a.id+b.id+c.id)*abs(random()%1e7) from tab a, tab b, tab c limit 5e5;
INSERT INTO tab (id) select (a.id+b.id+c.id)*abs(random()%1e7) from tab a, tab b, tab c limit 5e5;
select count(*) from tab;

¿Como funciona? Hace uso de eso si tabla tab :

id int
------
1
2

luego select a.id, b.id from tab a, tab b devuelve

a.id int | b.id int
------------------
    1    | 1
    2    | 1
    1    | 2
    2    | 2

y así. Después de la primera ejecución insertamos 2 filas, luego 2 ^ 3 = 8. (tres porque tenemos la tab a, tab b, tab c )

Después de la segunda ejecución insertamos adicional (2+8)^3=1000 filas

A continuación, insertamos aproximadamente max(1000^3, 5e5)=500000 filas y así sucesivamente ...

Este es el método más rápido conocido para mí de poblar bases de datos SQLite.


Soy capaz de hacer la consulta dinámica. Esta es mi mesa:

CREATE TABLE "tblPlanner" ("probid" text,"userid" TEXT,"selectedtime" DATETIME,"plannerid" TEXT,"isLocal" BOOL,"applicationid" TEXT, "comment" TEXT, "subject" TEXT)

y estoy obteniendo todos los datos a través de un JSON , así que después de obtener todo dentro de un NSArray , seguí esto:

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

Y finalmente la consulta de salida es esta:

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')

que también funciona bien con el código y puedo guardar todo en SQLite con éxito.

Antes de esto hice dinámicas las consultas de UNION pero eso comenzó a dar un error de sintaxis. De todos modos, esto está funcionando bien para mí.


Tengo una consulta como la de abajo, pero con el controlador ODBC, SQLite tiene un error con "," dice. Ejecuto vbscript en HTA (Html ​​Application).

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())

en mysql lite no puede insertar varios valores, pero puede ahorrar tiempo al abrir la conexión solo una vez, luego hacer todas las inserciones y luego cerrar la conexión. Ahorra mucho tiempo



INSERT INTO TABLE_NAME 
            (DATA1, 
             DATA2) 
VALUES      (VAL1, 
             VAL2), 
            (VAL1, 
             VAL2), 
            (VAL1, 
             VAL2), 
            (VAL1, 
             VAL2), 
            (VAL1, 
             VAL2), 
            (VAL1, 
             VAL2), 
            (VAL1, 
             VAL2), 
            (VAL1, 
             VAL2); 




syntax