it-swarm-es.tech

¿Cómo vuelco los datos de algunas tablas SQLite3?

¿Cómo vuelco los datos, y solo los datos, no el esquema, de algunas tablas SQLite3 de una base de datos (no todas las tablas)? El volcado debe estar en formato SQL, ya que luego se puede volver a ingresar fácilmente en la base de datos y se debe hacer desde la línea de comandos. Algo como

sqlite3 db .dump

pero sin volcar el esquema y seleccionar las tablas a volcar.

166
pupeno

No dices lo que deseas hacer con el archivo volcado.

Usaría lo siguiente para obtener un archivo CSV, que puedo importar en casi todo

.mode csv 
-- use '.separator SOME_STRING' for something other than a comma.
.headers on 
.out file.csv 
select * from MyTable;

Si desea reinsertarse en una base de datos SQLite diferente, entonces:

.mode insert <target_table_name>
.out file.sql 
select * from MyTable;
203
CyberFonic

Puede hacer esto obteniendo la diferencia de los comandos .schema y .dump. por ejemplo con grep:

sqlite3 some.db .schema > schema.sql
sqlite3 some.db .dump > dump.sql
grep -vx -f schema.sql dump.sql > data.sql

El archivo data.sql solo contendrá datos sin esquema, algo como esto:

BEGIN TRANSACTION;
INSERT INTO "table1" VALUES ...;
...
INSERT INTO "table2" VALUES ...;
...
COMMIT;

Espero que esto te ayude.

142
jellyfish

No es la mejor manera, pero al menos no necesita herramientas externas (excepto grep, que es estándar en todas las cajas * nix)

sqlite3 database.db3 .dump | grep '^INSERT INTO "tablename"'

pero necesita hacer este comando para cada tabla que esté buscando.

Tenga en cuenta que esto no incluye el esquema.

36
polyglot

Puede especificar uno o más argumentos de la tabla para el comando especial .dump, por ejemplo .sqlite3 db ".dump 'table1' 'table2'".

34
Paul Egan

Cualquier respuesta que sugiera usar grep para excluir las líneas CREATE o simplemente tomar las líneas INSERT de la salida de sqlite3 $DB .dump fallará. Los comandos CREATE TABLE listan una columna por línea (de modo que excluir CREATE no lo obtendrá todo), y los valores en las líneas INSERT pueden tener nuevas líneas incrustadas (por lo que no puede capturar solo las líneas INSERT).

for t in $(sqlite3 $DB .tables); do
    echo -e ".mode insert $t\nselect * from $t;"
done | sqlite3 $DB > backup.sql

Probado en sqlite3 versión 3.6.20.

Si desea excluir ciertas tablas, puede filtrarlas con $(sqlite $DB .tables | grep -v -e one -e two -e three), o si desea obtener un subconjunto específico, cámbielo por one two three.

10
retracile

Como una mejora de la respuesta de Paul Egan, esto se puede lograr de la siguiente manera:

sqlite3 database.db3 '.dump "table1" "table2"' | grep '^INSERT'

--o--

sqlite3 database.db3 '.dump "table1" "table2"' | grep -v '^CREATE'

La advertencia, por supuesto, es que tienes que tener instalado grep.

8
Drew

En Python o Java o en cualquier lenguaje de alto nivel, el .dump no funciona. Necesitamos codificar la conversión a CSV a mano. Doy un ejemplo de Python. Otros, se apreciarían ejemplos:

from os import path   
import csv 

def convert_to_csv(directory, db_name):
    conn = sqlite3.connect(path.join(directory, db_name + '.db'))
    cursor = conn.cursor()
    cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
    tables = cursor.fetchall()
    for table in tables:
        table = table[0]
        cursor.execute('SELECT * FROM ' + table)
        column_names = [column_name[0] for column_name in cursor.description]
        with open(path.join(directory, table + '.csv'), 'w') as csv_file:
            csv_writer = csv.writer(csv_file)
            csv_writer.writerow(column_names)
            while True:
                try:
                    csv_writer.writerow(cursor.fetchone())
                except csv.Error:
                    break

Si tiene 'datos de panel', en otras palabras, muchas entradas individuales con id's agregan esto a with look y también vuelca estadísticas de resumen:

        if 'id' in column_names:
            with open(path.join(directory, table + '_aggregate.csv'), 'w') as csv_file:
                csv_writer = csv.writer(csv_file)
                column_names.remove('id')
                column_names.remove('round')
                sum_string = ','.join('sum(%s)' % item for item in column_names)
                cursor.execute('SELECT round, ' + sum_string +' FROM ' + table + ' GROUP BY round;')
                csv_writer.writerow(['round'] + column_names)
                while True:
                    try:
                        csv_writer.writerow(cursor.fetchone())
                    except csv.Error:
                        break 
6

De acuerdo con la documentación de SQLite para el Shell de línea de comandos para SQLite puede exportar una tabla de SQLite (o parte de una tabla) como CSV, simplemente configurando el "modo" a "csv" y luego ejecutar una consulta para extraer Las filas deseadas de la tabla:

sqlite> .header on
sqlite> .mode csv
sqlite> .once c:/work/dataout.csv
sqlite> SELECT * FROM tab1;
sqlite> .exit

Luego use el comando ".import" para importar datos CSV (valores separados por comas) en una tabla SQLite:

sqlite> .mode csv
sqlite> .import C:/work/dataout.csv tab1
sqlite> .exit

Lea la documentación adicional sobre los dos casos a considerar: (1) La tabla "tab1" no existe anteriormente y (2) la tabla "tab1" ya existe.

4
PeterCo

Revisión de otras posibles soluciones.

Incluir solo INSERTs

sqlite3 database.db3 .dump | grep '^INSERT INTO "tablename"'

Fácil de implementar, pero fallará si alguna de sus columnas incluye nuevas líneas

Modo de inserción SQLite

for t in $(sqlite3 $DB .tables); do
    echo -e ".mode insert $t\nselect * from $t;"
done | sqlite3 $DB > backup.sql

Esta es una solución agradable y personalizable, pero no funciona si sus columnas tienen objetos de blob como el tipo 'Geometría' en spatialite

Difunde el volcado con el esquema

sqlite3 some.db .schema > schema.sql
sqlite3 some.db .dump > dump.sql
grep -v -f schema.sql dump > data.sql

No estoy seguro de por qué, pero no está funcionando para mí.

Otra posible (nueva) solución.

Probablemente no haya una mejor respuesta a esta pregunta, pero una que me funciona es grep the inserts teniendo en cuenta que hay nuevas líneas en los valores de columna con una expresión como esta

grep -Pzo "(?s)^INSERT.*\);[ \t]*$"

Para seleccionar que las tablas se vuelquen, .dump admite un argumento LIKE para coincidir con los nombres de las tablas, pero si esto no es suficiente, probablemente una opción mejor sea un script simple.

TABLES='table1 table2 table3'

echo '' > /tmp/backup.sql
for t in $TABLES ; do
    echo -e ".dump ${t}" | sqlite3 database.db3 | grep -Pzo "(?s)^INSERT.*?\);$" >> /tmp/backup.sql
done

o, algo más elaborado para respetar claves externas y encapsular todo el volcado en una sola transacción

TABLES='table1 table2 table3'

echo 'BEGIN TRANSACTION;' > /tmp/backup.sql
echo '' >> /tmp/backup.sql
for t in $TABLES ; do
    echo -e ".dump ${t}" | sqlite3 $1 | grep -Pzo "(?s)^INSERT.*?\);$" | grep -v -e 'PRAGMA foreign_keys=OFF;' -e 'BEGIN TRANSACTION;' -e 'COMMIT;' >> /tmp/backup.sql
done

echo '' >> /tmp/backup.sql
echo 'COMMIT;' >> /tmp/backup.sql

Tenga en cuenta que la expresión grep fallará si ); es una cadena presente en cualquiera de las columnas

Para restaurarlo (en una base de datos con las tablas ya creadas)

sqlite3 -bail database.db3 < /tmp/backup.sql
3
Francisco Puga

El mejor método sería tomar el código que haría el volcado db sqlite3, excluyendo las partes del esquema.

Ejemplo de pseudo código:

SELECT 'INSERT INTO ' || tableName || ' VALUES( ' || 
  {for each value} ' quote(' || value || ')'     (+ commas until final)
|| ')' FROM 'tableName' ORDER BY rowid DESC

Ver: src/Shell.c:838 (para sqlite-3.5.9) para el código real

Incluso puede simplemente tomar ese Shell y comentar las partes del esquema y usarlo.

2
harningt

Esta versión funciona bien con nuevas líneas dentro de inserciones:

sqlite3 database.sqlite3 .dump | grep -v '^CREATE'

En la práctica, se excluyen todas las líneas que comienzan con CREATE, que es menos probable que contengan nuevas líneas.

2
Elia Schito

La respuesta por retráctil debería ser la más cercana, pero no funciona para mi caso. Una consulta de inserción se rompió en el medio y la exportación se detuvo. No estoy seguro de cuál es la razón. Sin embargo, funciona bien durante .dump.

Finalmente escribí una herramienta para dividir el SQL generado desde .dump:

https://github.com/motherapp/sqlite_sql_parser/

0
Walty Yeung