web-dev-qa-db-ja.com

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

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

sqlite3 db .dump

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

168
pupeno

ダンプされたファイルで何をしたいのかを言わない。

次を使用して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;
206
CyberFonic

これを行うと、.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;

これがあなたのお役に立てば幸いです。

143
jellyfish

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

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

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

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

37
polyglot

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

34
Paul Egan

Grepを使用してCREATE行を除外すること、またはsqlite3 $DB .dump出力からINSERT行を取得することを示唆する回答は、すべて失敗します。 CREATE TABLEコマンドは行ごとに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で置き換えます。

10
retracile

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

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

-または-

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

もちろん、警告はgrepをインストールする必要があるということです。

8
Drew

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ルックに追加し、要約統計もダンプします。

        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 

SQLiteのコマンドラインシェル のSQLiteドキュメントによると、単に "mode"を "csv"に設定してから、SQLiteテーブル(またはテーブルの一部)を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"が既に存在する。

4
PeterCo

最良の方法は、スキーマパーツを除き、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
harningt

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

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
3
Francisco Puga

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

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

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

2
Elia Schito

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

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

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

0
Walty Yeung