エクスポートはSQL文ではなく、シェルの仕事
SQLiteには、PostgresやMySQLにあるような COPY ... TO や SELECT INTO OUTFILE は用意されていません。データのエクスポートは sqlite3 コマンドラインシェル側の仕事で、.mode、.headers、.output、.dump といったドットコマンドで操作します。この4つさえ押さえておけば、どんなデータベースからでもCSV・JSON・プレーンテキスト、さらにはSQLダンプまで自由に出力できます。
イメージとしてはこんな感じです。シェルに対して、結果を どう フォーマットするか(.mode)、カラム名を 含めるか どうか(.headers)、出力を どこへ 送るか(.output)を指定する。あとはクエリを実行すれば、その結果がそのままファイルに書き出されます。
では、実際に試すための小さなデータベースを用意してみましょう。
3行4列のテーブルですね。これをいろいろな形式でエクスポートしていきます。
CSVエクスポート: .mode csv とヘッダー出力
CSV は最もよく使われるエクスポート形式です。表計算ソフトやデータパイプラインなど、たいていのツールが CSV を読み込めます。sqlite3 シェル上で次のように実行します。
sqlite> .mode csv
sqlite> .headers on
sqlite> .output users.csv
sqlite> SELECT * FROM users;
sqlite> .output stdout
ここで起きたことを整理します:
.mode csvは各行をカンマ区切り(CSV)形式で整形し、カンマ・引用符・改行を含むフィールドは自動でクォートしてくれます。.headers onを指定すると、1 行目にカラム名のヘッダーが付きます。これを付けないとヘッダーなしの CSV になってしまうので、たいていの場合は付けておきたいはずです。.output users.csvでクエリ結果をファイルへリダイレクトします。これ以降の出力は画面ではなくファイルに書き込まれます。SELECTが実行され、結果は画面には何も表示されずファイルへ書き出されます。.output stdoutで出力先を端末に戻します。次のクエリ結果をまた画面で確認できるようになります。
出力されたファイル:
id,name,email,signup_date
1,"Ada Lovelace",ada@example.com,2025-01-15
2,"Boris Johnson",boris@example.com,2025-02-03
3,"Carmen Diaz",carmen@example.com,2025-03-22
テーブル全体だけでなく、任意のクエリの結果もエクスポートできます。フィルタや結合、集計をかけた上で、その出力をリダイレクトすればOKです。
sqlite> .output recent_users.csv
sqlite> SELECT name, email FROM users WHERE signup_date >= '2025-02-01';
sqlite> .output stdout
シェルから一発で実行する
わざわざ対話モードに入る必要はありません。ドットコマンドとSQLを、OSのシェルからsqlite3にパイプで流し込むだけでOKです。
sqlite3 mydb.sqlite <<EOF
.headers on
.mode csv
.output users.csv
SELECT * FROM users;
EOF
スクリプトや cron で回すなら、この書き方が定番です。手で打ち直さずに何度でも同じ結果が得られますし、.output の指定はそのセッション内だけで完結するので、状態がどこかに残ってしまう心配もありません。
JSON で出力する: .mode json
Web アプリや JSON を読み込むツールにデータを渡したいときは、.mode json を使うと各行をオブジェクトとした配列で出力してくれます。
sqlite> .mode json
sqlite> .output users.json
sqlite> SELECT * FROM users;
sqlite> .output stdout
The file:
[{"id":1,"name":"Ada Lovelace","email":"ada@example.com","signup_date":"2025-01-15"},
{"id":2,"name":"Boris Johnson","email":"boris@example.com","signup_date":"2025-02-03"},
{"id":3,"name":"Carmen Diaz","email":"carmen@example.com","signup_date":"2025-03-22"}]
JSON ではキー自体がヘッダーの役割を果たすので、.headers は使えません。ネストしたオブジェクトにしたい、フィールド名を変えたいといったカスタムな形にしたい場合は、クエリの中で json_object() を使って組み立てます。
ここまでくれば、行ごとのJSON文字列を好きな構造で作れるようになります。さらに json_group_array() と組み合わせれば、結果全体を1つのJSONドキュメントにまとめることもできます。
SQL全体をダンプする:.dump
.dump は、CSVやJSON出力とはそもそも目的が違うコマンドです。スキーマとデータの両方を CREATE TABLE と INSERT 文の形で書き出した .sql ファイルを生成してくれるので、空っぽの状態からデータベースをまるごと復元できます。
sqlite3 mydb.sqlite .dump > backup.sql
A snippet of what comes out:
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
email TEXT NOT NULL,
signup_date TEXT NOT NULL
);
INSERT INTO users VALUES(1,'Ada Lovelace','ada@example.com','2025-01-15');
INSERT INTO users VALUES(2,'Boris Johnson','boris@example.com','2025-02-03');
INSERT INTO users VALUES(3,'Carmen Diaz','carmen@example.com','2025-03-22');
COMMIT;
リストアはこの逆の操作で、書き出したファイルを新しいデータベースに流し込むだけです。
sqlite3 restored.sqlite < backup.sql
.dumpは、バックアップ、テストデータのバージョン管理用スナップショット、マシン間の移行に最適なツールです。インデックス、トリガー、ビューなど、スキーマに含まれる要素をすべて保持してくれます。
特定のテーブルだけをダンプする
.dumpにはテーブル名(またはパターン)を指定できるので、出力範囲を絞り込めます:
sqlite3 mydb.sqlite ".dump users" > users_only.sql
これは users テーブルのスキーマと行だけをダンプします。残りのテーブルは持ち込まずに、特定のテーブルだけを別のデータベースへコピーしたいときに便利です。パターンマッチもできて、.dump 'log_%' のように書けば log_ で始まるテーブルをまとめてダンプできます。
データを含めずスキーマだけ出力する
データの中身は要らないけど構造だけ欲しい、というケースもあります。ドキュメント用、クリーンな開発環境の構築、あるいは複数データベース間でスキーマを比較したいときなどですね。そんなときは .schema を使うと、CREATE 文だけを出力できます。
sqlite3 mydb.sqlite .schema > schema.sql
テーブル名を一緒に指定すれば、そのテーブルだけを取り出せます:
sqlite3 mydb.sqlite ".schema users" > users_schema.sql
出力されるのは純粋な SQL(CREATE TABLE、CREATE INDEX、CREATE TRIGGER)なので、空のデータベースに対してそのまま実行できます。
知っておくと便利なその他のモード
.mode には CSV や JSON 以外にも色々なオプションがあります。よく使うものをいくつか紹介します。
.mode column -- 整列された列、ターミナルで読みやすい
.mode markdown -- パイプ区切り、GitHubフレンドリーな表
.mode html -- HTMLの<table>出力
.mode tabs -- タブ区切り値(TSV)
.mode insert users -- 指定したテーブル用のINSERT文を出力
.mode quote -- SQL形式でクオートされた値、検査に便利
.mode markdown を使えば、クエリ結果をそのまま README やプルリクエストに貼り付けられて便利です。.mode insert <table> はシードデータをサクッと作るのに重宝します。SELECT を流して出てきた INSERT 文をコピーし、フィクスチャファイルに貼り付けるだけでOKです。
sqlite> .mode insert users
sqlite> .output seed.sql
sqlite> SELECT * FROM users WHERE signup_date >= '2025-02-01';
sqlite> .output stdout
実践で気をつけたいポイント
.output stdout(または引数なしの.output)でターミナル出力に戻す。 これを忘れると、次のクエリの結果がファイルに吸い込まれて画面に何も表示されません。- CSV エクスポートでは型情報が失われます。 ファイル内ではすべて文字列扱いになり、再インポートする際は読み解くためのスキーマが必要になります。別の SQLite データベースに往復させたいなら
.dumpを使いましょう。 - 大きなエクスポートはストリーミング処理されます。
.outputは行が生成されるそばから書き出していくので、メモリに収まらないサイズのテーブルでも問題なくダンプできます。 - 稼働中のデータベースをホットバックアップしたい場合、
.dumpでも動きますが、専用の.backupコマンド(カリキュラムの後半で扱います)の方が高速かつ安全です。SQLite のオンラインバックアップ API を使うためです。
次回:データの読み出し
これで書き込み系の全体像が見えました。INSERT、UPDATE、DELETE、UPSERT、RETURNING、CSV からのインポート、そして CSV へのエクスポートまでカバーしています。次はデータベース活用のもう半分、データを効率よく読み出す方法です。実際の作業時間で一番長く付き合うことになるのが SELECT 文で、それが次ページのテーマです。
よくある質問
SQLiteのテーブルをCSVに書き出すには?
sqlite3 シェルでCSVモードに切り替え、ヘッダーをオンにして、出力先をファイルに指定してからクエリを実行します。順番としては .mode csv → .headers on → .output users.csv → SELECT * FROM users; の流れです。書き出しが終わったら .output stdout で出力先をターミナルに戻しておきましょう。
.dump とCSVエクスポートはどう違う?
.dump は CREATE TABLE と INSERT 文を含む .sql ファイルを出力するので、これさえあればデータベースをまるごと復元できます。一方CSVは1つのクエリやテーブルの「行データ」だけで、スキーマは含まれません。バックアップや別環境への移行には .dump、Excelや他ツールに渡したいときはCSV、と使い分けるのが基本です。
SQLiteのクエリ結果をJSONで出力できる?
できます。シェルで .mode json をセットして SELECT を流すのが一番手軽です。もっと細かく形を制御したい場合は、組み込み関数の json_object() や json_group_array() を使ってクエリ側でJSONを組み立てる方法もあります。サクッと出すなら .mode json、構造をきちんと作り込みたいなら関数ベース、と覚えておけばOKです。