Come posso scaricare i dati di alcune tabelle SQLite3?


183

Come posso scaricare i dati e solo i dati, non lo schema, di alcune tabelle SQLite3 di un database (non tutte le tabelle)? Il dump dovrebbe essere in formato SQL, poiché dovrebbe essere facilmente reinserito nel database in un secondo momento e dovrebbe essere eseguito dalla riga di comando. Qualcosa di simile a

sqlite3 db .dump

ma senza scaricare lo schema e selezionando quali tabelle scaricare.


In quale formato? Qualcosa in particolare o stai solo cercando un backup leggibile dall'uomo? Per favore specificare.
dmckee --- ex-moderatore gattino

1
Voglio scaricare in formato SQL, in modo da poterlo ripristinare facilmente. Ho aggiunto queste informazioni alla domanda principale.
pupeno,

Risposte:


214

Non stai dicendo cosa desideri fare con il file scaricato.

Vorrei usare quanto segue per ottenere un file CSV, che posso importare in quasi tutto

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

Se si desidera reinserire in un diverso database SQLite, quindi:

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

C'è un modo per farlo a livello di codice usando le istruzioni SQL? Posso vedere come farlo usando l'interprete, ma se volessi scrivere una sceneggiatura?
Coleifer,

4
È possibile inserire le dichiarazioni in un file (ad esempio sample.txt) e quindi invocarlo utilizzando: sqlite3 db.sq3 <sample.txt
CyberFonic

" Oppure usa il comando .once invece di .output e l'output verrà reindirizzato per il singolo comando successivo prima di tornare alla console. Usa .output senza argomenti per iniziare a scrivere di nuovo sull'output standard. " Documenti SQLite
ruffin

156

Puoi farlo ottenendo la differenza tra i comandi .schema e .dump. ad esempio con grep:

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

data.sql il file conterrà solo dati senza schema, qualcosa del genere:

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

Spero che questo ti aiuta.


5
@anurageldorado è semplice sql. corri e bastasqlite3 some.db < data.sql
meduse

Per alcuni rasson non funziona per me. Ho bisogno di usi in giro. sqlite3 storage/db/jobs.s3db .schema jobs > schema.sqlnon funziona, ma echo '.schema' jobs | sqlite3 storage/db/jobs.s3db > schema.sqlfunziona bene
abkrim

2
Sembrava una buona soluzione, ma nel mio caso la maggior parte delle linee viene effettivamente rimossa da grep. Il comando .schema genera lo schema di ogni tabella su più righe, quindi è presente solo una riga); e grep rimuove tutte le righe contenenti );L'aggiunta -xdell'opzione a grep risolve questo problema.
Sunder,

38

Non è il modo migliore, ma al leasing non ha bisogno di strumenti esterni (tranne grep, che è comunque standard su * nix box)

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

ma devi eseguire questo comando per ogni tabella che stai cercando.

Si noti che questo non include lo schema.


1
Ho usatosqlite3 Database.s3db .dump
Jader Dias il

3
Ciò si interromperà se quegli inserti presentano nuove righe nei valori. Meglio usare grep -v '^CREATE'come suggerito in una delle altre risposte
dequis

1
l'utilizzo grep -v '^CREATE;si interromperà se le CREATEistruzioni presentano interruzioni di riga (cosa che a volte fanno). La cosa migliore, IMO, non è quella di eliminare automaticamente le CREATEdichiarazioni, ma di modificarle manualmente. Usa qualsiasi editor di testo di cui hai bisogno, cerca CREATEe rimuovi manualmente quelle istruzioni. Finché il database non è enorme (e dal momento che stai usando sqlite, immagino che sia nota), allora questo è piuttosto semplice.
Dan Jones,

ma il grep della creazione prenderà anche la creazione dalle viste. come posso rimuoverlo?
Silve2611,

35

È possibile specificare uno o più argomenti di tabella al comando speciale .dump, ad es sqlite3 db ".dump 'table1' 'table2'".


4
quando aggiungo più nomi di tabella come hai detto, mi dà questo output: Uso: .dump? - preserv-rowids? ? COME-modello?
mwm,

1
@mwm sto osservando lo stesso problema in sqlite3 3.31.1 (2020/01/27). Il log delle modifiche non dice nulla al riguardo. (A proposito, --preserve-rowidsfunziona ma non è affatto documentato.)
ynn

11

Qualsiasi risposta che suggerisce l'utilizzo di grep per escludere le CREATElinee o semplicemente afferrare le INSERTlinee sqlite3 $DB .dumpdall'output fallirà male. I CREATE TABLEcomandi elencano una colonna per riga (quindi l'esclusione CREATEnon la otterrà interamente) e i valori sulle INSERTrighe possono avere linee incorporate (quindi non puoi afferrare solo le INSERTlinee).

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

Testato su sqlite3 versione 3.6.20.

Se si desidera escludere determinate tabelle con cui è possibile filtrarle $(sqlite $DB .tables | grep -v -e one -e two -e three)o se si desidera ottenere un sottoinsieme specifico, sostituirlo con one two three.


9

Come miglioramento della risposta di Paul Egan, ciò può essere ottenuto come segue:

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

--o--

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

L'avvertimento, ovviamente, è che devi avere grep installato.


1
Mi piace questa. Come bonus aggiuntivo, funziona ancora se hai un file SQL scaricato in giro, solo cat database.sql | grep '^INSERT' > database_inserts.sql(lo stesso per lo schema, sostituisci congrep '^CREATE'
trisweb

2
@trisweb, ovviamente intendi grep '^INSERT' < database.sql > database_inserts.sqlche catè superfluo
Sebastian,

1
Niente di superfluo al riguardo. I catcosti praticamente non sono eseguibili e rendono la catena di input per l'output molto più chiara. Certo, potresti anche scrivere < database.sql grep '^INSERT' ...ma una pipe esplicita è molto più facile da leggere.
rjh

1
quando aggiungo più nomi di tabella come hai detto, mi dà questo output: Uso: .dump? - preserv-rowids? ? COME-modello?
mwm,

-1: La ricerca di righe con CREATE è un'idea inutile. Quasi ogni vista o trigger in particolare, se contiene commenti, richiede più di una riga.
ceving

6

In Python o Java o in qualsiasi linguaggio di alto livello il .dump non funziona. Dobbiamo codificare manualmente la conversione in CSV. Faccio un esempio di Python. Altri, sarebbero apprezzati esempi:

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

Se disponi di "dati del pannello", in altre parole molte singole voci con ID aggiungono questo al look con e scarica anche le statistiche di riepilogo:

        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 

4

Secondo la documentazione SQLite per Command Line Shell Per SQLite è possibile esportare una tabella SQLite (o parte di una tabella) come CSV, semplicemente impostando la "modalità" su "csv" e quindi eseguire una query per estrarre le righe desiderate di la tavola:

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

Quindi utilizzare il comando ".import" per importare i dati CSV (valori separati da virgola) in una tabella SQLite:

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

Leggere la documentazione aggiuntiva sui due casi da considerare: (1) la tabella "tab1" non esiste in precedenza e (2) la tabella "tab1" esiste già.


3

Il metodo migliore sarebbe quello di prendere il codice che farebbe il dump sqlite3 db, escludendo le parti dello schema.

Esempio di pseudo codice:

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

Vedere: src/shell.c:838 (per sqlite-3.5.9) per il codice effettivo

Potresti anche solo prendere quella shell e commentare le parti dello schema e usarlo.


3

Revisione di altre possibili soluzioni

Includi solo INSERTI

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

Facile da implementare ma fallirà se una delle tue colonne include nuove linee

Modalità di inserimento SQLite

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

Questa è una soluzione piacevole e personalizzabile, ma non funziona se le colonne hanno oggetti BLOB come il tipo "Geometria" in spatialite

Diff il dump con lo schema

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

Non so perché, ma non funziona per me

Un'altra (nuova) soluzione possibile

Probabilmente non c'è una risposta migliore a questa domanda, ma una cosa che funziona per me è grep gli inserti tenendo conto che ci sono nuove righe nei valori della colonna con un'espressione come questa

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

Per selezionare le tabelle da scaricare, si .dumpammette un argomento LIKE che corrisponda ai nomi delle tabelle, ma se questo non è abbastanza probabilmente un semplice script è l'opzione migliore

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, qualcosa di più elaborato per rispettare le chiavi esterne e incapsulare tutto il dump in una sola transazione

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

Tieni presente che l'espressione grep fallirà se );è presente una stringa in una delle colonne

Per ripristinarlo (in un database con le tabelle già create)

sqlite3 -bail database.db3 < /tmp/backup.sql

2

Questa versione funziona bene con le nuove linee all'interno degli inserti:

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

In pratica esclude tutte le righe che iniziano con le CREATEquali è meno probabile che contengano newline


0

La risposta di retracile dovrebbe essere la più vicina, ma non funziona nel mio caso. Una query di inserimento si è appena interrotta nel mezzo e l'esportazione si è appena fermata. Non sono sicuro di quale sia la ragione. Tuttavia funziona benissimo durante .dump.

Alla fine ho scritto uno strumento per suddividere l'SQL generato da .dump:

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


-3

È possibile effettuare una selezione nelle tabelle inserendo virgole dopo ogni campo per produrre un csv oppure utilizzare uno strumento GUI per restituire tutti i dati e salvarli in un csv.


2
La mia intenzione era quella di produrre un file SQL che potesse facilmente essere aggiunto nuovamente al DB.
pupeno,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.