it-swarm-id.com

Bagaimana cara membuang data dari beberapa tabel SQLite3?

Bagaimana cara membuang data, dan hanya data, bukan skema, dari beberapa tabel SQLite3 dari database (tidak semua tabel)? Dump harus dalam format SQL, karena harus dengan mudah dimasukkan kembali ke dalam database nanti dan harus dilakukan dari baris perintah. Sesuatu seperti

sqlite3 db .dump

tetapi tanpa membuang skema dan memilih tabel mana yang akan dibuang.

170
pupeno

Anda tidak mengatakan apa yang ingin Anda lakukan dengan file yang dibuang.

Saya akan menggunakan yang berikut ini untuk mendapatkan file CSV, yang dapat saya impor ke hampir semuanya

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

Jika Anda ingin memasukkan kembali ke dalam database SQLite yang berbeda maka:

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

Anda dapat melakukan ini dengan mendapatkan perbedaan perintah .schema dan .dump. misalnya dengan grep:

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

data.sql file hanya akan berisi data tanpa skema, seperti ini:

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

Saya harap ini membantu Anda.

144
jellyfish

Bukan cara terbaik, tetapi setidaknya tidak memerlukan alat eksternal (kecuali grep, yang merupakan standar pada * nix box)

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

tetapi Anda perlu melakukan perintah ini untuk setiap tabel yang Anda cari.

Perhatikan bahwa ini tidak termasuk skema.

37
polyglot

Anda dapat menentukan satu atau lebih argumen tabel ke perintah khusus .dump, mis .sqlite3 db ".dump 'table1' 'table2'".

34
Paul Egan

Setiap jawaban yang menyarankan penggunaan grep untuk mengecualikan baris CREATE atau hanya mengambil baris INSERT dari _ sqlite3 $DB .dump output akan gagal parah. Perintah CREATE TABLE mencantumkan satu kolom per baris (jadi tidak termasuk CREATE tidak akan mendapatkan semuanya), dan nilai pada baris INSERT dapat memiliki baris baru yang disematkan (sehingga Anda tidak dapat mengambil hanya baris INSERT).

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

Diuji pada sqlite3 versi 3.6.20.

Jika Anda ingin mengecualikan tabel tertentu, Anda dapat memfilternya dengan $(sqlite $DB .tables | grep -v -e one -e two -e three), atau jika Anda ingin mendapatkan subset tertentu ganti dengan one two three.

10
retracile

Sebagai peningkatan pada jawaban Paul Egan, ini dapat dicapai sebagai berikut:

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

--atau--

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

Peringatannya, tentu saja, adalah bahwa Anda harus menginstal grep.

8
Drew

Dalam Python atau Java atau bahasa tingkat tinggi apa pun .dump tidak berfungsi. Kita perlu mengkodekan konversi ke CSV dengan tangan. Saya memberi contoh Python. Lainnya, contoh-contoh akan dihargai:

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

Jika Anda memiliki 'data panel, dengan kata lain banyak entri individual dengan id menambahkan ini ke tampilan with dan juga membuang statistik ringkasan:

        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

Menurut dokumentasi SQLite untuk Command Line Shell For SQLite Anda dapat mengekspor tabel SQLite (atau bagian dari tabel) sebagai CSV, cukup dengan mengatur "mode" ke "csv" dan kemudian menjalankan kueri untuk mengekstrak baris tabel yang diinginkan:

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

Kemudian gunakan perintah ".import" untuk mengimpor data CSV (comma separated value) ke dalam tabel SQLite:

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

Silakan baca dokumentasi lebih lanjut tentang dua kasus untuk mempertimbangkan: (1) Tabel "tab1" sebelumnya tidak ada dan (2) tabel "tab1" sudah ada.

4
PeterCo

Metode terbaik adalah dengan mengambil kode dump sqlite3 db akan lakukan, tidak termasuk bagian skema.

Contoh kode palsu:

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

Lihat: src/Shell.c:838 (untuk sqlite-3.5.9) untuk kode aktual

Anda bahkan mungkin hanya mengambil Shell itu dan mengomentari bagian skema dan menggunakannya.

3
harningt

Tinjau solusi lain yang mungkin

Sertakan hanya INSERT

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

Mudah diimplementasikan tetapi akan gagal jika salah satu kolom Anda menyertakan baris baru

Mode penyisipan SQLite

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

Ini adalah solusi yang bagus dan dapat disesuaikan, tetapi tidak berfungsi jika kolom Anda memiliki objek gumpalan seperti tipe 'Geometri' dalam spasial

Bedakan dump dengan skema

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

Tidak yakin mengapa, tetapi tidak berhasil untuk saya

Solusi (baru) lainnya yang mungkin

Mungkin tidak ada jawaban terbaik untuk pertanyaan ini, tetapi salah satu yang berfungsi untuk saya adalah ambil sisipan dengan mempertimbangkan baris baru dalam nilai kolom dengan ekspresi seperti ini

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

Untuk memilih tabel jangan dibuang .dump mengakui argumen LIKE untuk mencocokkan nama tabel, tetapi jika ini tidak cukup mungkin skrip sederhana adalah pilihan yang lebih baik

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

atau, sesuatu yang lebih rumit untuk menghormati kunci asing dan merangkum semua dump hanya dalam satu transaksi

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

Pertimbangkan bahwa ekspresi grep akan gagal jika ); adalah string yang ada di salah satu kolom

Untuk mengembalikannya (dalam database dengan tabel sudah dibuat)

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

Versi ini berfungsi baik dengan baris baru di dalam sisipan:

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

Dalam praktiknya mengecualikan semua baris yang dimulai dengan CREATE yang cenderung mengandung baris baru

2
Elia Schito

Jawaban dengan retracile haruslah jawaban yang paling dekat, tetapi tidak berhasil untuk kasus saya. Satu permintaan memasukkan baru saja putus di tengah dan ekspor hanya berhenti. Tidak yakin apa alasannya. Namun itu berfungsi dengan baik selama .dump.

Akhirnya saya menulis alat untuk memisahkan SQL yang dihasilkan dari .dump:

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

0
Walty Yeung