Comment vider les données, et uniquement les données, pas le schéma, de certaines tables SQLite3 d'une base de données (pas toutes les tables)? Le vidage doit être au format SQL, car il doit être facilement ré-entré ultérieurement dans la base de données et doit être effectué à partir de la ligne de commande. Quelque chose comme
sqlite3 db .dump
mais sans vider le schéma et sélectionner les tables à vider.
Vous ne dites pas ce que vous souhaitez faire avec le fichier vidé.
Je voudrais utiliser ce qui suit pour obtenir un fichier CSV, que je peux importer dans presque tout
.mode csv
-- use '.separator SOME_STRING' for something other than a comma.
.headers on
.out file.csv
select * from MyTable;
Si vous souhaitez réinsérer dans une autre base de données SQLite, alors:
.mode insert <target_table_name>
.out file.sql
select * from MyTable;
Vous pouvez faire cela en obtenant la différence entre les commandes .schema et .dump. par exemple avec grep:
sqlite3 some.db .schema > schema.sql
sqlite3 some.db .dump > dump.sql
grep -vx -f schema.sql dump.sql > data.sql
Le fichier data.sql
ne contiendra que des données sans schéma, comme ceci:
BEGIN TRANSACTION;
INSERT INTO "table1" VALUES ...;
...
INSERT INTO "table2" VALUES ...;
...
COMMIT;
J'espère que ceci vous aide.
Ce n’est pas la meilleure solution, mais au moins n’a pas besoin d’outils externes (sauf grep, qui est de toutes façons standard sur les boîtes * nix)
sqlite3 database.db3 .dump | grep '^INSERT INTO "tablename"'
mais vous devez faire cette commande pour chaque table que vous recherchez cependant.
Notez que cela n'inclut pas le schéma.
Vous pouvez spécifier un ou plusieurs arguments de table pour la commande spéciale .dump, par exemple .sqlite3 db ".dump 'table1' 'table2'"
.
Toute réponse suggérant d'utiliser grep pour exclure les lignes CREATE
ou simplement saisir les lignes INSERT
de la sortie sqlite3 $DB .dump
échouera mal. Les commandes CREATE TABLE
répertorient une colonne par ligne (ainsi, l'exclusion de CREATE
ne l'obtiendra pas en totalité), et les valeurs des lignes INSERT
peuvent comporter des traits nouveaux juste les lignes INSERT
).
for t in $(sqlite3 $DB .tables); do
echo -e ".mode insert $t\nselect * from $t;"
done | sqlite3 $DB > backup.sql
Testé sur la version 3.6.20 de sqlite3.
Si vous souhaitez exclure certaines tables, vous pouvez les filtrer avec $(sqlite $DB .tables | grep -v -e one -e two -e three)
ou si vous souhaitez obtenir un sous-ensemble spécifique, remplacez-le par one two three
.
Pour améliorer la réponse de Paul Egan, cela peut être accompli comme suit:
sqlite3 database.db3 '.dump "table1" "table2"' | grep '^INSERT'
--ou--
sqlite3 database.db3 '.dump "table1" "table2"' | grep -v '^CREATE'
La mise en garde, bien sûr, est que vous devez avoir installé grep.
Dans Python ou Java ou tout autre langage de haut niveau, le fichier .dump ne fonctionne pas. Nous devons coder la conversion au format CSV à la main. Je donne un exemple Python. D'autres, des exemples seraient appréciés:
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 vous avez des données de panel, en d'autres termes, de nombreuses entrées individuelles avec un identifiant ajoutent ceci au look avec et produira également des statistiques récapitulatives:
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
Selon la documentation de SQLite pour le ligne de commande shell pour SQLite , vous pouvez exporter une table SQLite (ou une partie d’une table) au format CSV, en définissant simplement le "mode" sur "csv", puis en exécutant un script. requête pour extraire les lignes désirées de la table:
sqlite> .header on
sqlite> .mode csv
sqlite> .once c:/work/dataout.csv
sqlite> SELECT * FROM tab1;
sqlite> .exit
Utilisez ensuite la commande ".import" pour importer des données CSV (valeurs séparées par des virgules) dans une table SQLite:
sqlite> .mode csv
sqlite> .import C:/work/dataout.csv tab1
sqlite> .exit
Veuillez lire la documentation complémentaire sur les deux cas à prendre en compte: (1) Le tableau "tab1" n’existait pas auparavant et (2) le tableau "tab1" existait déjà.
La meilleure méthode serait de prendre le code que ferait le dump sqlite3 db, en excluant les parties de schéma.
Exemple de pseudo-code:
SELECT 'INSERT INTO ' || tableName || ' VALUES( ' ||
{for each value} ' quote(' || value || ')' (+ commas until final)
|| ')' FROM 'tableName' ORDER BY rowid DESC
Voir: src/Shell.c:838
(pour sqlite-3.5.9) pour le code actuel
Vous pouvez même simplement prendre ce shell, commenter les parties du schéma et l'utiliser.
Inclut uniquement les INSERT
sqlite3 database.db3 .dump | grep '^INSERT INTO "tablename"'
Facile à mettre en œuvre mais cela échouera si l'une de vos colonnes inclut de nouvelles lignes
Mode d'insertion SQLite
for t in $(sqlite3 $DB .tables); do
echo -e ".mode insert $t\nselect * from $t;"
done | sqlite3 $DB > backup.sql
Ceci est une solution agréable et personnalisable, mais cela ne fonctionne pas si vos colonnes ont des objets blob tels que 'Geometry' de type spatialite
Diffère le dump avec le schéma
sqlite3 some.db .schema > schema.sql
sqlite3 some.db .dump > dump.sql
grep -v -f schema.sql dump > data.sql
Je ne sais pas pourquoi, mais ça ne marche pas pour moi
Il n’ya probablement pas de meilleure réponse à cette question, mais celle qui marche pour moi est grep les insertions en tenant compte des nouvelles lignes dans les valeurs de colonne avec un expression comme celle-ci
grep -Pzo "(?s)^INSERT.*\);[ \t]*$"
Pour sélectionner les tables, effectuez un vidage. .dump
admet un argument LIKE correspondant aux noms des tables. Toutefois, si cela ne suffit pas, il est probablement préférable d'utiliser un simple script.
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
ou, quelque chose de plus élaboré pour respecter les clés étrangères et encapsuler tout le dump en une seule transaction
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
Tenez compte du fait que l'expression grep échouera si );
est une chaîne présente dans l'une des colonnes.
Pour le restaurer (dans une base de données avec les tables déjà créées)
sqlite3 -bail database.db3 < /tmp/backup.sql
Cette version fonctionne bien avec les nouvelles lignes à l'intérieur des inserts:
sqlite3 database.sqlite3 .dump | grep -v '^CREATE'
En pratique, exclut toutes les lignes commençant par CREATE
qui est moins susceptible de contenir des nouvelles lignes
La réponse par rétracile devrait être la plus proche, mais cela ne fonctionne pas pour mon cas. Une requête d'insertion vient de se briser au milieu et l'exportation vient de s'arrêter. Je ne sais pas quelle est la raison. Cependant, cela fonctionne bien pendant .dump
.
Enfin, j'ai écrit un outil pour scinder le SQL généré à partir de .dump
: