2008-09-16 9 views
158

Wie speichere ich die Daten und nur die Daten, nicht das Schema, von einigen SQLite3-Tabellen einer Datenbank (nicht alle Tabellen)? Der Speicherauszug sollte im SQL-Format vorliegen, da er später einfach erneut in die Datenbank eingegeben werden sollte und über die Befehlszeile erfolgen sollte. So etwas wieWie kann ich die Daten einiger SQLite3-Tabellen ausgeben?

sqlite3 db .dump 

aber ohne das Schema und die Auswahl der Tabellen zu dumpen.

+0

In welches Format?Irgendetwas Bestimmtes, oder suchen Sie nur nach einem menschlich lesbaren Backup? Bitte angeben. – dmckee

+1

Ich möchte in SQL-Format ausgeben, damit ich es leicht wiederherstellen kann. Ich habe diese Informationen zur Hauptfrage hinzugefügt. – Pablo

Antwort

-3

Sie können eine Auswahl für die Tabellen treffen, die nach jedem Feld Kommas einfügen, um ein CSV zu erzeugen, oder ein GUI-Tool verwenden, um alle Daten zurückzugeben und sie in einem CSV zu speichern.

+2

Meine Absicht war es, eine SQL-Datei zu erstellen, die einfach wieder in die DB hinzugefügt werden konnte. – Pablo

2

Die beste Methode wäre, den Code zu nehmen, den der sqlite3-Db-Dump ausführen würde, mit Ausnahme von Schemateilen.

Beispiel Pseudocode:

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

See: src/shell.c:838 (für SQLite-3.5.9) für den tatsächlichen Code

Sie könnten sogar, dass die Schale nehmen nur und kommentieren die Schema-Teile aus und verwendet diesen.

189

Sie sagen nicht, was Sie mit der gedumpten Datei machen möchten.

würde ich folgendes bekommen eine CSV-Datei verwenden, die ich in fast alles importieren

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

Wenn Sie in eine andere SQLite-Datenbank wieder einsetzen wollen, dann:

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

Gibt es eine Möglichkeit programmgesteuert SQL-Anweisungen zu verwenden? Ich kann sehen, wie man es mit dem Interpreter macht, aber was ist, wenn ich ein Skript schreiben möchte? – coleifer

+3

Sie können Ihre Anweisungen in eine Datei (zB sample.txt) setzen und dann mit: sqlite3 db.sq3 CyberFonic

35

Nicht der Der beste Weg, aber zumindest keine externen Tools (außer grep, die ohnehin bei * nix-Boxen Standard ist)

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

aber Sie müssen diesen Befehl für jede Tabelle tun, die Sie suchen.

Beachten Sie, dass dies kein Schema enthält.

+1

Ich benutzte 'sqlite3 Database.s3db .dump' –

+3

Dies wird brechen, wenn diese Einsätze Zeilenumbrüche haben die Werte. Besser verwenden Sie 'grep -v '^ CREATE' wie in einer der anderen Antworten vorgeschlagen – dequis

+1

mit' grep -v'^CREATE; 'wird brechen, wenn die' CREATE' Anweisungen Zeilenumbrüche in ihnen haben (was sie manchmal tun). Am besten, IMO, werden die CREATE-Anweisungen nicht automatisch entfernt, sondern manuell bearbeitet. Verwenden Sie einfach den von Ihnen benötigten Texteditor, suchen Sie nach "CREATE" und entfernen Sie diese Anweisungen manuell. Solange die Datenbank nicht riesig ist (und da du sqlite verwendest, würde ich es raten), ist das ziemlich einfach. –

31

Sie können einen oder mehrere Tabellenargumente für den speziellen Befehl .dump angeben, z. sqlite3 db ".dump 'table1' 'table2'".

+0

Wenn ich mehrere Tabellennamen hinzufüge, wie Sie erwähnt haben, gibt es mir diese Ausgabe: Verwendung: .dump? - preserve-rowids? "Gefällt mir" -Muster? – mwm

123

Sie können dies tun, Unterschied der .schema und .dump-Befehle zu bekommen. zum Beispiel mit grep:

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

Ich hoffe, das hilft Ihnen:

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

data.sql Datei nur Daten ohne Schema, so etwas wie dieses enthalten.

+0

irgendwelche direkten Befehle, um sie zurück zu importieren? – dorado

+3

@anureldeldorado ist es einfacher sql. einfach ausführen 'sqlite3 some.db jellyfish

+0

Für einige rasson funktioniert nicht für mich. Ich brauche Anwendungen um. 'sqlite3 storage/db/jobs.s3db .schema jobs> schema.sql' funktioniert nicht, aber' echo '.schema' jobs | sqlite3 storage/db/jobs.s3db> schema.sql' funktioniert gut – abkrim

8

Als Verbesserung Paul Egan Antwort, kann dies wie folgt erreicht werden:

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

--oder--

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

Der Nachteil ist natürlich, ist, dass Sie müssen Grep installiert.

+1

Ich mag diesen. Als zusätzlichen Bonus funktioniert es immer noch, wenn Sie eine SQL-Datei haben, die nur "cat database.sql" enthält grep '^ INSERT'> database_inserts.sql' (gleiches für Schema, durch 'grep 'ersetzen^CREATE'' – trisweb

+2

@trisweb, natürlich meinst du' grep '^ INSERT' database_inserts.sql' das 'cat 'ist überflüssig – Sebastian

+1

Nichts überflüssig darüber. Der' cat' kostet im Grunde nichts zum Ausführen und macht die Kette der Eingabe viel schärfer. Natürlich könnte man auch ' rjh

2

Diese Version funktioniert gut mit Zeilenumbrüche innerhalb Einsätze:

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

In der Praxis mit CREATE beginnen alle Zeilen ausschließt, die weniger wahrscheinlich ist, enthalten newlines

9

Jede Antwort, die grep schlägt auszuschließen Die CREATE Zeilen oder einfach nur die INSERT Zeilen aus dem sqlite3 $DB .dump Ausgang wird schlecht ausfallen. Die CREATE TABLE Befehle listen eine Spalte pro Zeile auf (so wird CREATE nicht alles davon erhalten), und Werte auf den INSERT Zeilen können eingebettete Zeilenumbrüche enthalten (so können Sie nicht nur die INSERT Zeilen greifen).

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

Getestet auf sqlite3 Version 3.6.20.

Wenn Sie bestimmte Tabellen ausschließen möchten, können Sie sie mit $(sqlite $DB .tables | grep -v -e one -e two -e three) filtern, oder wenn Sie eine bestimmte Untermenge erhalten möchten, ersetzen Sie diese durch one two three.

6

In Python oder Java oder einer anderen Hochsprache funktioniert die .dump nicht. Wir müssen die Umwandlung in CSV von Hand kodieren. Ich gebe ein Python-Beispiel. Andere würden Beispiele geschätzt:

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 

Wenn Sie ‚Paneldaten haben, also viele einzelne Einträge mit ids dies mit Blick auf die hinzufügen und Dumps auch zusammenfassende Statistiken:

 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 
0

Die Antwort mit Retracile sollte die nächste sein, aber es funktioniert nicht für meinen Fall. Eine Insert-Abfrage ist gerade in der Mitte kaputt gegangen und der Export hat gerade gestoppt. Nicht sicher, was der Grund ist. Es funktioniert jedoch gut während .dump.

Schließlich habe ich ein Werkzeug für die die SQL von .dump erzeugt aufgeteilt:

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

1

Bewertung von anderen möglichen Lösungen

nur Fügen Sie INSERTs

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

Leicht zu implementieren, aber es wird fehlschlagen, wenn eine Ihrer Spalten inkl ude neue Linien

SQLite Einfügemodus

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

Dies ist eine schöne und individuell anpassbare Lösung, aber es funktioniert nicht, wenn Ihre Spalten Blob Objekte wie ‚Geometrie‘ Typ in spatialite

haben Diff der Dump mit dem Schema

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

Nicht sicher wh y, aber nicht für mich arbeiten

Weitere (neu) mögliche Lösung

Wahrscheinlich gibt keine beste Antwort auf diese Frage, aber eine, die für mich arbeitet, um die Einsätze grep zu berücksichtigen, die neu Linien in dem Spaltenwert mit einem expression like this

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

die Tabellen auszuwählen Sie werden abgeladen .dump ein LIKE Argument gibt die Tabellennamen übereinstimmen, aber wenn dies wahrscheinlich ein einfaches Skript ist nicht genug ist bessere Option

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 

oder, etwas ausgefeilteren Fremdschlüssel zu respektieren und in nur einer Transaktion

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 

Berücksichtigen Sie dabei alle Dump-kapseln, dass der grep Ausdruck fehl, wenn ); eine Zeichenkette in einer der Spalten ist

um es (in einer Datenbank mit den Tabellen bereits erstellt)

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

nach der SQLite Dokumentation wiederherstellen für die Command Line Shell For SQLite können Sie, indem Sie den „Modus“ eine SQLite-Tabelle (oder einen Teil einer Tabelle) als CSV, einfach exportieren „csv“ und dann eine Abfrage ausführen, um die gewünschten Zeilen der Tabelle zu extrahieren:

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

dann den ".import" Befehl verwenden, um CSV (comma Separated Value) von Daten in eine SQLite-Tabelle zu importieren:

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

Bitte die weitere Dokumentation über die beiden Fälle lesen zu berücksichtigen: (1) Table "tab1" tut vorher nicht vorhanden und (2) Tabelle "tab1" existiert bereits.