一部のSQLite3テーブルのデータをダンプするにはどうすればよいですか?


183

データベースの一部のSQLite3テーブル(すべてのテーブルではない)のデータ(スキーマではなく)のみをダンプするにはどうすればよいですか?後でデータベースに簡単に再入力でき、コマンドラインから実行する必要があるため、ダンプはSQL形式である必要があります。何かのようなもの

sqlite3 db .dump

ただし、スキーマをダンプしたり、ダンプするテーブルを選択したりする必要はありません。


どのフォーマットに?特に何か、または人間が読めるバックアップを探しているだけですか?ご指定ください。
dmckee ---元モデレーターの子猫

1
SQL形式にダンプして、簡単に復元できるようにしたいと考えています。その情報をメインの質問に追加しました。
プペノ2008

回答:


214

ダンプされたファイルに対して何をしたいかを言っているのではありません。

以下を使用して、ほとんどすべてにインポートできるCSVファイルを取得します。

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

別のSQLiteデータベースに再挿入する場合は、次のようにします。

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

SQLステートメントを使用してプログラムでこれを行う方法はありますか?インタプリタを使用してそれを行う方法を見ることができますが、スクリプトを記述したい場合はどうなりますか?
coleifer 2014年

4
ステートメントをファイル(たとえば、sample.txt)に入れ、次を使用してそれを呼び出すことができます:sqlite3 db.sq3 <sample.txt
Cyber​​Fonic

" または、.outputの代わりに.onceコマンドを使用し、コンソールに戻る前に、出力は単一の次のコマンドにのみリダイレクトされます。標準出力への書き込みを再開するには、引数なしで.outputを使用します。 " SQLite docs
ruffin

156

これを行うと、.schemaコマンドと.dumpコマンドの違いを取得できます。たとえばgrepの場合:

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

data.sql ファイルには、スキーマのないデータのみが含まれます。次のようなものです:

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

これがお役に立てば幸いです。


5
@anurageldoradoそれはプレーンSQLです。ただ走るsqlite3 some.db < data.sql
クラゲ

一部のラッソンは私のために動作しません。周りの用途が必要です。sqlite3 storage/db/jobs.s3db .schema jobs > schema.sqlうまくいかないが、echo '.schema' jobs | sqlite3 storage/db/jobs.s3db > schema.sqlうまくいく
アブクリム

2
それは良い解決策のように見えましたが、私の場合、ほとんどの行は実際にはgrepによって削除されています。.schemaコマンドは、各テーブルのスキーマを複数行で生成するため);、のみを含む行があり、grepにオプションを);追加する-xことを含むすべての行がgrepによって削除されます。この問題は、grepに追加すると解決します。
サンダー

38

最善の方法ではありませんが、少なくとも外部ツールは必要ありません(とにかく* nixボックスに標準であるgrepを除く)。

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

ただし、探しているテーブルごとにこのコマンドを実行する必要があります。

これにはスキーマが含まれないことに注意してください。


1
私が使用しましたsqlite3 Database.s3db .dump
Jader Dias

3
これらの挿入の値に改行がある場合、これは壊れます。grep -v '^CREATE'他の回答の1つで提案されているように使用する
Dequis

1
ステートメントに改行が含まれているgrep -v '^CREATE;場合(使用すると改行される場合)は、CREATE改行されます。IMOの最善の方法は、CREATEステートメントを自動的に取り除くのではなく、手動で編集することです。必要なテキストエディターを使用して、CREATEそれらのステートメントを検索し、手動で削除してください。データベースが巨大でない限り(そして、あなたがsqliteを使用しているので、それは注記だと思います)、これはかなり単純です。
Dan Jones

ただし、作成のgrepはビューから作成も取得します。どうすれば削除できますか?
Silve2611

35

.dump特殊コマンドに1つ以上のテーブル引数を指定できますsqlite3 db ".dump 'table1' 'table2'"


4
あなたが述べたように複数のテーブル名を追加すると、次の出力が得られます:使用法:.dump?-preserve-rowids??LIKE-PATTERN?
mwm 2017年

1
@mwmで同じ問題が発生していsqlite3 3.31.1 (2020/01/27)ます。変更ログはそれについて何も述べていません。(ちなみに、--preserve-rowids作業を行いますが、すべてでは文書化されていません。)
YNN

11

grepを使用してCREATE行を除外したりINSERTsqlite3 $DB .dump出力から行を取得したりすることを示唆する回答は、すべて失敗します。CREATE TABLEコマンドは1行につき1つの列を一覧表示する(除くのでCREATE、それのすべてを取得することはできません)、そして上の値INSERT(あなただけつかむことができないので、行が埋め込まれた改行を持つことができますINSERTライン)。

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

sqlite3バージョン3.6.20でテスト済み。

特定のテーブルを除外する場合は$(sqlite $DB .tables | grep -v -e one -e two -e three)、それらをでフィルタリングできます。または、特定のサブセットを取得する場合は、それをで置き換えone two threeます。


9

ポール・イーガンの答えの改善として、これは次のようにして達成できます。

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

-または-

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

もちろん、注意点は、grepをインストールする必要があることです。


1
私はこれが好きです。追加のボーナスとして、ダンプされたSQLファイルがぶらぶらしている場合でも機能cat database.sql | grep '^INSERT' > database_inserts.sqlします(スキーマと同じ、次のものに置き換えますgrep '^CREATE'
trisweb

2
@trisweb、もちろんあなたはgrep '^INSERT' < database.sql > database_inserts.sqlそれcatが不必要であることを意味します
Sebastian

1
それについて不必要なことは何もありません。cat基本的に実行するためには何も費用はかかりませんし、入力から出力への連鎖がより明確になります。もちろん、書き込むこともできます< database.sql grep '^INSERT' ...が、明示的なパイプの方がはるかに読みやすくなります。
rjh 2016

1
あなたが述べたように複数のテーブル名を追加すると、次の出力が得られます:使用法:.dump?-preserve-rowids??LIKE-PATTERN?
mwm 2017年

-1:CREATEを使用して行を検索するのは無意味なアイデアです。特にほとんどのビューまたはトリガーには、コメントが含まれている場合、複数の行が必要です。
2017

6

Python、Java、または高水準言語では、.dumpは機能しません。CSVへの変換を手動でコーディングする必要があります。Pythonの例を示します。その他、例をいただければ幸いです。

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

「パネルデータがある場合、つまり、idを持つ多くの個々のエントリは、これをwith lookに追加し、要約統計もダンプします。

        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

SQLiteのコマンドラインシェルのドキュメントによると、SQLite のSQLiteテーブル(またはテーブルの一部)をCSVとしてエクスポートするには、「モード」を「csv」に設定し、クエリを実行して目的の行を抽出します。テーブル:

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

次に、「。import」コマンドを使用して、CSV(カンマ区切り値)データをSQLiteテーブルにインポートします。

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

考慮すべき2つのケースに関する詳細なドキュメントをお読みください:(1)テーブル "tab1"は以前は存在していませんでした、(2)テーブル "tab1"はすでに存在しています。


3

最良の方法は、スキーマ部分を除いて、sqlite3 dbダンプが行うコードを取ることです。

擬似コードの例:

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

参照:src/shell.c:838 (sqlite-3.5.9の場合)実際のコード

そのシェルを使用してスキーマの一部をコメント化し、それを使用することもできます。


3

他の可能な解決策のレビュー

INSERTのみを含める

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

実装は簡単ですが、列に新しい行が含まれていると失敗します

SQLite挿入モード

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

これは優れたカスタマイズ可能なソリューションですが、列に 'Geometry'タイプのようなBLOBオブジェクトが含まれる場合は機能しません

ダンプをスキーマと比較する

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

理由はわからないが、うまくいかない

別の(新しい)可能な解決策

おそらくこの質問に対する最良の答えはありませんが、私にとってうまくいったのは、このような式で列値の新しい行であることを考慮に入れて挿入をgrepすることです

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

ダンプするテーブルを選択するには.dump、テーブル名と一致するようにLIKE引数を許可しますが、これで十分でない場合は、おそらく単純なスクリプトがより良いオプションです。

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

または、外部キーを尊重し、すべてのダンプを1つのトランザクションのみにカプセル化するようにさらに工夫されたもの

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

);いずれかの列に文字列が存在する場合、grep式は失敗することを考慮してください

それを復元するには(テーブルが既に作成されているデータベース内)

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

2

このバージョンは、挿入内の改行でうまく機能します。

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

実際にはCREATE、改行を含む可能性が低い行で始まるすべての行を除外します


0

retracileによる答えは最も近いはずですが、私の場合はうまくいきません。1つの挿入クエリが途中で途切れ、エクスポートが停止しました。理由がわからない。ただし、の間は正常に動作し.dumpます。

最後に、以下から生成されたSQLを分割するためのツールを作成しました.dump

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


-3

各フィールドの後にカンマを挿入してテーブルを選択し、csvを生成するか、GUIツールを使用してすべてのデータを返し、csvに保存できます。


2
私の意図は、DBに簡単に再追加できるSQLファイルを作成することでした。
pupeno 2008年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.