コーディングエージェントがタスクを完了したところだとする。マイグレーションを書いて実行し、dev.db にフィクスチャを投入した。サマリーには「orders.status をデフォルト値 'pending' で追加し、3,200行をバックフィルした」とある。信用する前に、自分の目で確かめたい。ORMが自分で書いていないマイグレーションを生成したときも、モバイルアプリがテスト端末でローカルデータベースに書き込み、画面が空になる原因を調べるためそのファイルを取り出したときも、同じ状況になる。

手っ取り早いのは、行の内容をAIチャットに貼り付けて何がおかしいか聞くことだ。だが実際のデータベースの大半では、それをやってはいけない。ステージング環境からコピーした dev.db には顧客のメールアドレスが入っている。モバイルアプリのデータベースにはセッショントークンが、CLIの状態ファイルにはAPIキーが入っている。ファイルは人間が、すでにそれが存在するマシン上で読む必要がある。

ビューアでSQLiteファイルを開く →

このビューアはブラウザのタブ内でファイルを開く。テーブル、ビュー、カラム、インデックス、CREATE 文を表示し、行をページ送りし、入力した任意のSQLを実行し、CSVをエクスポートする。アップロードは一切発生せず、このツールページはアナリティクスや広告のスクリプトも読み込まない。この先のガイドでは、SQLiteファイルの中身、ビューアがそれをどう読むか、そしてファイルが期待通りに表示されないケースについて説明する。

ブラウザ版SQLite Viewerが適したケース

状況確認することブラウザ版ビューアが適する理由
エージェントやスクリプトがマイグレーションを実行した新しいカラム、デフォルト値、バックフィルされた値、新しいインデックスファイルを開き、構造パネルを読み、SELECT を一回実行し、タブを閉じる
ORMのマイグレーションレビューSQLiteが実際に保存した CREATE TABLE(モデルと異なる場合がある)ビューアは保存されている CREATE 文をそのまま表示する
モバイルアプリのローカルデータベースアプリがテスト端末に書き込んだ行デスクトップクライアントのインストールが不要。ファイルは自分のマシンに留まる
Electronアプリやコマンドラインツールの状態設定、キャッシュ、キューテーブル多くのデスクトップアプリやCLIは単一のSQLiteファイルに状態を保持する
テストフィクスチャの確認リポジトリにコミットされたフィクスチャデータベースフィクスチャがテストの前提通りの内容を持つか確認する
同僚へのデータ共有データベース全体ではなく1件のクエリ結果クエリを実行し、CSVをエクスポートして送る
本番実行前に文を試すUPDATE や DELETE の効果SQLはインメモリコピー上で実行され、ディスク上のファイルは変化しない
Next.js/RailsのローカルSQLite確認Prisma や ActiveRecord がプロトタイプ用に書き込んだ dev.sqlite3 の中身ORMのマイグレーション結果を、コマンドを叩かずその場で確認できる

ファイルをその場で編集する場合、非常に大きなファイル、暗号化されたデータベースには、ローカルツールを使う。以下の各節で、その理由とケースごとの推奨ツールを説明する。

SQLiteファイルの中身

SQLiteデータベースは1つの普通のファイルだ。フォーマットは SQLite Database File Format ページに詳細に文書化されており、そこに書かれたいくつかの事実だけで、このビューアの動作のほとんどが説明できる。

100バイトのヘッダー

すべてのデータベースファイルの先頭100バイトがファイルヘッダーだ。先頭16バイトは固定されている。

53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00
S  Q  L  i  t  e     f  o  r  m  a  t     3  \0

これはUTF-8文字列 SQLite format 3 の後にnullバイトが続いたものだ。この16バイトで始まらないファイルは、純粋なSQLite 3データベースではない。拡張子は何の判断材料にもならない。.db、.sqlite、.sqlite3、.db3 はいずれも一般的で、.db という拡張子のファイルが実は別物というケースは珍しくない。

ファイルの挙動がおかしいときに役立つ、その他のヘッダーフィールド。

オフセットサイズフィールド
162バイトページサイズ(ビッグエンディアン)
181バイトファイルフォーマット書き込みバージョン
191バイトファイルフォーマット読み込みバージョン
404バイトスキーマクッキー(スキーマ変更のたびに増加)
564バイトテキストエンコーディング
604バイトユーザーバージョン(アプリがマイグレーションカウンタとして使うことが多い)
684バイトアプリケーションID
964バイトファイルを最後に書き込んだSQLiteライブラリのバージョン番号

ページサイズは2のべき乗だ。3.7.0.1までのバージョンでは512から32,768バイトが許容されていた。SQLite 3.7.1(2010年)で65,536バイトのページが追加された。65,536は2バイトに収まらないため、値 1 として格納される。バイト18と19は、ロールバックジャーナル方式のデータベースでは両方とも 1、WAL方式のデータベースでは両方とも 2 になる。つまりファイルを開かなくてもジャーナルモードが分かる。

スキーマテーブル

ファイルのページ1は sqlite_schema というテーブルのルートだ。古いコードや多くのチュートリアルでは sqlite_master と呼ばれるが、これは今も有効なエイリアスだ。このテーブルは type、name、tbl_name、rootpage、sql の5つのカラムを持つ。すべてのテーブル、インデックス、ビュー、トリガーが1行ずつ対応し、sql カラムには元の CREATE 文のテキストが格納されている。

sqlite_ で始まる名前は、SQLiteが自分自身のために作る内部オブジェクトだ。AUTOINCREMENT のカウンタ用の sqlite_sequence や、クエリプランナの統計情報用の sqlite_stat1 などがある。アプリケーションがこのプレフィックスでオブジェクトを作ることはSQLiteが許可しない。

ビューアがファイルを読み込む仕組み

ファイルをドロップしてからテーブル一覧が表示されるまでの流れを順番に示す。

1. サイズチェック。 100MBを超えるファイルは、1バイトも読まれる前に拒否される。理由はメモリだ。ファイルはディスクから読み込んだバッファとして1回、SQLiteエンジン内でもう1回保持される。大きなデータベースを2重に保持すると、ブラウザタブが不安定になる。

2. ヘッダーチェック。 ビューアはFile APIで先頭100バイトだけを読み、先頭16バイトを SQLite format 3\0 と比較する。ファイルが100バイト未満か、バイト列が一致しない場合は「Not a SQLite 3 database」エラーになる。拡張子は一切信用されない。

3. エンジンのロード。 ヘッダーチェックを通過した後で初めて、ページはSQLiteエンジンを取得する。エンジンは sql.js 1.14.2で、これはSQLite 3.49.1をWebAssemblyにコンパイルしたものだ。2つのファイルは圧縮後で約340KBあり、ブラウザは一度だけそれらを取得する。誤ったファイル、PNG、CSVではこのダウンロードは発生しない。

4. インメモリでのオープン。 ファイル全体が Uint8Array に読み込まれ、new SQL.Database(bytes) に渡される。sql.jsはそのデータベースを仮想のインメモリファイルシステム内に保持する。この時点以降、すべてのクエリはこのコピーに対して実行される。

5. オブジェクト一覧。 ビューアは sqlite_master に対してテーブルとビューを問い合わせる。内部の sqlite_% オブジェクトは一覧からは隠されるが、SQLエディタからは問い合わせ可能だ。各テーブルには COUNT(*) が付与される。ビューは件数なしで一覧表示される。

6. 構造。 テーブルやビューを選択すると、ビューアはテーブル値関数形式のプラグマを実行する。

SELECT name, type, "notnull", dflt_value, pk FROM pragma_table_info(?);
SELECT name, "unique", origin FROM pragma_index_list(?);
SELECT name FROM pragma_index_info(?) ORDER BY seqno;

これらのプラグマのテーブル値形式は、SQLite 3.16.0(2017年)以降存在する。構造パネルには各カラムの名前、宣言された型、NOT NULL、デフォルト値、主キー内での位置が表示される。インデックスパネルには名前、カラム、一意性、originが表示される。originは CREATE INDEX で作られたインデックスでは c、UNIQUE 制約で作られたものは u、PRIMARY KEY 制約で作られたものは pk になる。インデックスのエントリがrowidまたは式の場合、pragma_index_info はカラム名として NULL を返す。ビューアはそのようなエントリを (expr) と表示する。インデックスの下には、スキーマテーブルに格納されている通りの CREATE 文がそのまま表示される。

7. 行。 データグリッドは LIMIT 100 OFFSET n で、テーブルを100行ずつページ送りする。範囲を示す行には「Rows 101–200 of 3,200」のように表示され、常に自分がどこにいるか分かる。

ビューアがSQLに組み込むすべてのテーブル名・カラム名はダブルクォートで囲まれ、名前の中にダブルクォートが含まれる場合は二重化される。order、user data、"quoted" といった名前のテーブルや、非ラテン文字の名前も正しく開ける。

「アップロードしない」の意味

ファイルはFile APIを通じてディスクからページのメモリへ直接渡される。このツールが発行するネットワークリクエストはエンジンファイルの取得のみで、それも同一サイト内の静的ファイルだ。入力が非公開のデータベースであることを踏まえ、このツールページはサイトのアナリティクスや広告スクリプトを読み込まないよう設定されている。タブを閉じるかリロードすると、インメモリコピーは消える。

SQLiteの値はカラムの表記通りとは限らない

SQLiteファイルを読む際の混乱の多くは、その型システムに起因する。詳細は Datatypes In SQLite ページに書かれているが、要点は以下の通り。

  • 値は5つのストレージクラスのいずれかを持つ: NULL、INTEGER、REAL、TEXT、BLOB。
  • SQLiteは動的型付けを採用している。型はカラムではなく値に属する。
  • 宣言されたカラムの型は親和性(TEXT、NUMERIC、INTEGER、REAL、BLOB)を設定するだけであり、SQLiteは可能な場合にそれを使って挿入時に値を変換する。

親和性は、宣言された型名に対する部分文字列ルールによって決まる。INT を含む型はINTEGER親和性になる。CHAR、CLOB、TEXT を含む型はTEXT親和性になるため、VARCHAR(255) はTEXTとして扱われ、255という数値は無視される。BLOB、または型の指定がない場合はBLOB親和性になる。REAL、FLOA、DOUB はREALになる。それ以外はすべてNUMERICになる。

つまり実際には、INTEGER と宣言されたカラムでも、何かが書き込みさえすれば文字列 'n/a' を保持できてしまう。created_at DATETIME と宣言したORMが、ある行ではISO-8601形式のテキストを、別の行ではUnixタイムスタンプを格納することもありうる。SQLiteには日付型もbool型も存在しない。日付はTEXT、REAL(ユリウス日)、INTEGER(Unix時間)のいずれかで格納され、真偽値は整数の 0 と 1 で格納される。

ビューアは宣言されたカラムの型ではなく、実際に返ってきた値をもとに各セルを描画する。

値グリッド内での表示CSVエクスポートでの表示
NULL淡色の NULL マーカー空フィールド
空文字列 ''空のセル空フィールド
数値(INTEGERまたはREAL)右揃え格納されたまま
テキストテキストとして表示。長いテキストはセル内で切り詰め完全な値。必要に応じてクォート
BLOBBLOB · 4 B · 89504E47(バイト長と先頭16バイトの16進表記)全内容を大文字16進表記で出力

カラムの内容がおかしいと感じたら、SQLiteに直接何が入っているか尋ねる。

SELECT typeof(created_at) AS storage_class, COUNT(*)
FROM orders
GROUP BY 1;

これが text と integer の両方を返す場合、2つの異なるコードパスがそのカラムを異なる形式で書き込んでいることになる。SQLite 3.37.0(2021年)で追加された STRICT テーブルは、カラムの型として INT、INTEGER、REAL、TEXT、BLOB、ANY のみを許可し、型が一致しない値を拒否する。保存されている CREATE 文が STRICT で終わっていれば、そのテーブルでは型混在の問題は起こり得ない。

インメモリコピーに対してSQLを実行する

データグリッドの下にあるエディタは、SQLite 3.49.1が解釈できる任意のSQLを受け付ける。Run SQL を押すか、Ctrl/Cmd + Enterを押す。

  • 複数の文を一度に実行。 エディタ内のすべての文が順番に実行される。結果グリッドには、SELECT や UPDATE ... RETURNING のようにカラムを返す最後の文の結果が表示される。
  • エラーはSQLiteそのものから返る。 入力ミスがあると、ステータス行に near "SELEC": syntax error のようなSQLite自身のメッセージが表示される。直前の結果はクリアされるため、新しい結果と混同することはない。
  • データを変更する文は「Done. N row(s) changed in the in-memory copy.」と報告する。この件数は実行前後の total_changes() の差分から算出される。
  • スキーマの変更は検知される。 実行によってデータかスキーマバージョンが変化した場合、テーブル一覧が再読み込みされる。実行した CREATE TABLE は一覧にすぐ現れ、INSERT や DELETE の後は行数も更新される。
  • 大きな結果セット。 ページの応答性を保つため、グリッドは先頭1,000行のみを描画し、その旨を表示する。Export CSV は常に結果の全行を書き出す。

見慣れないデータベースを調べる際に役立つクエリをいくつか挙げる。

-- インデックスやトリガーを含む、すべてのオブジェクトとそのCREATE文
SELECT type, name, tbl_name, sql FROM sqlite_master ORDER BY type, name;

-- 多くのアプリがヘッダーに保持しているマイグレーションカウンタ
PRAGMA user_version;

-- テーブルに宣言されている外部キー
SELECT * FROM pragma_foreign_key_list('orders');

-- ファイルの破損をチェック
PRAGMA integrity_check;

書き込みはメモリ内に留まる

ブラウザは選択したファイルへの書き込みアクセス権を持たない。エンジンはメモリ上のコピーに対して動作するため、INSERT、UPDATE、DELETE、CREATE、DROP はすべて実行され、ビューアはその効果を表示するが、ディスク上のファイルはそのままの状態を保つ。変更はページをリロードするか別のファイルを開くと消える。このツールには、編集済みのコピーをダウンロードするオプションはない。

このため、このエディタは本番実行前に文を試すための安全な場所になる。例えば、クリーンアップが何行に影響するかを確認してから、残る行を見ることができる。

DELETE FROM sessions WHERE expires_at < unixepoch();
SELECT COUNT(*) AS remaining FROM sessions;

カスケード削除をテストする場合、1点注意が必要だ。新しいSQLite接続では、アプリケーション側が有効化しない限り外部キー制約は無効になっており、これはビューアでも同様だ。テストで ON DELETE CASCADE を発火させたい場合は、まず PRAGMA foreign_keys = ON; を実行する。

実際のファイルを変更するには、自分のマシン上で sqlite3 コマンドラインシェルか DB Browser for SQLite を使う。

CSVのエクスポート

Export CSV ボタンは2箇所にある。データグリッドの上にあるものは、現在のページだけでなく、選択中のテーブルまたはビューの全行をエクスポートする。SQLエディタの下にあるものは、直近のクエリの結果全体をエクスポートする。

出力はRFC 4180に従う。カンマ区切り、CRLF改行、カラム名を含むヘッダー行、そしてカンマ・ダブルクォート・CR・LFを含むフィールドは " でクォートされる。フィールド内のダブルクォートは二重化される。ファイル名はテーブル名に由来し、英数字と .、_、- 以外の文字は _ に置き換えられる。クエリ結果の場合は query.csv になる。

CSVというフォーマットゆえに生じる2つの帰結がある。

  • NULL と空文字列はどちらも空フィールドになる。この違いが重要な場合は、エクスポート前のクエリで COALESCE(col, '<null>') や col IS NULL AS col_is_null を選択する。
  • BLOBは大文字の16進表記になる。4バイトのPNGシグネチャは 89504E47 としてエクスポートされる。これによりCSVは有効なテキストのまま保たれ、ほとんどの言語では、Pythonの bytes.fromhex() のような1回の呼び出しで元に戻せる。

同僚にデータを渡すときは、相手が必要とするクエリ結果だけをエクスポートする。データベースファイル自体は手元に残る。

落とし穴とエッジケース

最近の行が見当たらない: WALファイル

これは最もよくある驚きのケースだ。Write-Ahead Logging ページで説明されているWALモードでは、SQLiteはコミット済みの変更をすぐにはメインのデータベースファイルへ書き込まない。データベース名に -wal サフィックスを付けた別ファイルに追記し、それに加えて -shm インデックスファイルも使う。チェックポイントによって、トランザクションがWALからメインファイルへ移される。デフォルトでは、WALが1,000ページに達すると自動的にチェックポイントが実行され、最後の接続が閉じられるとWALは通常削除される。

そのため、実行中のアプリから app.db をコピーしたり、アプリが開いた状態のスマートフォンから取り出したりすると、最新のトランザクションがまだ app.db-wal に残っていることがある。ビューアはメインファイルしか読まないため、その行は表示されない。SQLiteのドキュメントも、データベースファイルをそのWALから切り離すと、コミット済みのトランザクションが失われたり、データベースが破損したりする可能性があると警告している。

ヘッダーのバイト18と19を見れば、そのファイルがWALを使っているか分かる(両方とも 2 ならWAL)。WALをメインファイルに統合するには、書き込みを行っているアプリケーションを閉じてから、以下を実行する。

sqlite3 app.db "PRAGMA wal_checkpoint(TRUNCATE);"

TRUNCATE はすべてのフレームをチェックポイントした後、WALファイルを0バイトに切り詰める。その後で改めて app.db を開く。ロールバックモードのデータベースに残った -journal ファイルについても同様だ。ビューアはメインファイルしか読まないため、先にそのファイルを所有するアプリケーションか sqlite3 シェルにデータベースを開かせておく。

データベースだと分かっているのに「Not a SQLite 3 database」と出る

暗号化されたデータベースはこのエラーを起こす。SQLCipher は先頭16バイトにランダムなソルトを格納し、残りを暗号化するため、ファイル全体がランダムなデータのように見え、SQLite format 3 のヘッダーは失われる。SQLite Encryption Extension(SEE)もファイルを暗号化する。ビューアは暗号化されたデータベースを開けない。sqlcipher シェルで復号するか、SQLCipherファイルに対応した DB Browser for SQLite でファイルを開く。

同じエラーは、.db という名前でも実は別のファイルである場合や、途中で切れたコピーでも発生する。head -c 16 app.db | xxd で先頭バイトを確認する。

ファイルが100MBを超えている

この上限が固定なのは、データベースを開いている間メモリ上に2重に保持されるためだ。より大きなファイルの場合は、ローカルで sqlite3 app.db を実行するか、先に小さい抽出を作る。

sqlite3 big.db "ATTACH 'small.db' AS s; CREATE TABLE s.orders AS SELECT * FROM orders WHERE created_at >= '2026-09-01';"

その後、small.db をビューアで開く。

テーブルが行の代わりにエラーを表示する

一部のテーブルは、SQLiteのコアに含まれないコードを必要とする。SpatiaLiteのジオメトリテーブル、sqlite-vec のベクターテーブル、FTS5全文検索インデックス、R-Treeの空間インデックスといった仮想テーブルは、それらを作成したアプリケーションにコンパイルされたモジュールに依存する。このビューアが使うsql.js 1.14.2ビルドには fts5 や rtree モジュールが含まれておらず、そのようなテーブルへの問い合わせはSQLite自身のエラー、例えば no such module: fts5 を返す。

このようなテーブルの行数取得が失敗すると、一覧には — と表示され、データペインにはエラーが表示される。データベースの他の部分は引き続き閲覧できる。FTS5はデータを通常の「シャドウ」テーブル(例えば notes_fts_content)にも保持しており、それらは読み取り可能な通常のテーブルだ。

何もマッチしないクエリ

0行にマッチした SELECT でも、カラムのヘッダーは表示され、ステータス行には「0 row(s)」と表示される。これは、クエリが実行され、カラム名が正しいことを示しているので、確認すべきは WHERE 句だと分かる。SELECT COUNT(*) ... WHERE ... は常に1行を返し、答えを明確にしてくれる。

長いテキストと横に長いテーブル

セルの幅には上限があり、長いテキストは省略記号で切り詰められる。60文字を超えるテキストは、ホバーすると先頭最大2,000文字までがツールチップで表示される。カラムに格納されたJSONドキュメント全体を読むには、その値だけを選択して結果をCSVでエクスポートするか、クエリで json_extract() を使って必要な部分を取り出す。

稼働中のデータベースを安全にコピーする

アプリケーションが書き込んでいる最中に cp でファイルをコピーすると、内容が破綻したコピーになることがある。SQLite 3.15.0から使える VACUUM INTO は、トランザクション的に一貫性のあるスナップショットを新しいファイルに書き出し、元のファイルには触れない。このスナップショットは、WALのコミット済みの内容も含んだ単一のファイルになる。

sqlite3 app.db "VACUUM INTO 'snapshot.db'"

コード例

Python: ヘッダーを調べてから読み取り専用でカウントする

標準ライブラリの sqlite3 モジュールは、URIを使ってファイルを読み取り専用で開ける。このスクリプトは、ビューアと同じ方法でヘッダーをチェックし、ページサイズとジャーナルモードを表示し、各テーブルの行数を一覧表示する。

import sqlite3
import sys

path = sys.argv[1]
with open(path, "rb") as f:
    header = f.read(100)

if len(header) < 100 or header[:16] != b"SQLite format 3\x00":
    sys.exit(f"{path}: no SQLite 3 header (encrypted, truncated, or not a database)")

page_size = int.from_bytes(header[16:18], "big")
if page_size == 1:
    page_size = 65536                      # 1は64KiBページを表すマジックバリュー
journal = "WAL" if header[18] == 2 else "rollback"
print(f"page size: {page_size}  journal mode: {journal}")

con = sqlite3.connect(f"file:{path}?mode=ro", uri=True)   # 読み取り専用
tables = con.execute(
    "SELECT name FROM sqlite_master WHERE type = 'table' "
    "AND name NOT LIKE 'sqlite\\_%' ESCAPE '\\' ORDER BY name"
).fetchall()
for (name,) in tables:
    quoted = '"' + name.replace('"', '""') + '"'
    count = con.execute(f"SELECT COUNT(*) FROM {quoted}").fetchone()[0]
    print(f"{name:<32}{count:>10}")
con.close()

JavaScript: Node.jsで同じエンジンを使う

sql.jsはNode.js上でも動く。これはブラウザ版ツールと同じモデルだ。ファイルはメモリに読み込まれ、書き込みはコピーのみを変更する。

import { readFileSync } from "node:fs";
import initSqlJs from "sql.js";

const bytes = readFileSync(process.argv[2]);
const SQL = await initSqlJs();
const db = new SQL.Database(bytes);          // ファイルのインメモリコピー

const [schema] = db.exec(
  "SELECT type, name FROM sqlite_master WHERE type IN ('table', 'view') ORDER BY name"
);
for (const [type, name] of schema?.values ?? []) console.log(type.padEnd(6), name);

// 書き込みはコピーのみを変更する。ディスク上のファイルは触れられない。
db.run("DELETE FROM users WHERE email LIKE ?", ["%@example.com"]);
console.log("rows deleted in memory:", db.getRowsModified());

// db.export() は、変更後のデータベースを保持したい場合にUint8Arrayとして返す。
db.close();

Bash: 閲覧用にファイルを準備し、CLIからエクスポートする

# 未反映のWALトランザクションをメインファイルに統合する(先に書き込み元のアプリを閉じる)
sqlite3 app.db "PRAGMA wal_checkpoint(TRUNCATE);"

# または、一貫性のある単一ファイルのスナップショットを取得し、元のファイルには触れない
sqlite3 app.db "VACUUM INTO 'snapshot.db'"

# どこかで開く前に、ヘッダーを確認しておく
head -c 16 snapshot.db | xxd

# シェルからのCSVエクスポート。hex() はビューアと同様にBLOBをテキストとして保持する
sqlite3 -header -csv snapshot.db \
  "SELECT id, email, hex(avatar) AS avatar FROM users LIMIT 100" > users.csv

この hex() の呼び出しが重要だ。sqlite3 シェルはBLOBカラムを生のバイト列としてCSVに書き込むため、ほとんどのCSVリーダーにとってファイルが壊れてしまう。

他のSQLiteツールとの比較

これらのツールはそれぞれ異なる用途に向いている。

ツール実行環境読み取り対象ファイルへの書き込み暗号化ファイル
ZeroTool SQLite Viewerブラウザタブ、インストール不要最大100MBの1ファイルなし。変更はインメモリコピー内に留まる非対応
sqlite3 コマンドラインシェルローカルのターミナルWALを含むローカルディスク上のファイルあり非対応(sqlcipher シェルを使う)
DB Browser for SQLiteWindows/macOS/Linux向けデスクトップアプリ、オープンソースローカルディスク上のファイルあり対応(SQLCipher)

sqlite3 シェルは基準となるリファレンスツールだ。ファイルをその場で、独自のサイズ制限なしに開き、WALも読み、スクリプトとの相性もいい。見るだけなら sqlite3 -readonly app.db を使う。制約は、ドットコマンドを知っている必要があることと、横に長いテーブルをターミナルで読む必要があることだ。

DB Browser for SQLiteは本格的なデスクトップエディタだ。テーブルの作成・変更、グリッド上でのセル編集、SQLCipher暗号化の追加・解除ができる。ファイルを変更する必要がある場合に使う。

ブラウザ版ビューアは手早く確認するためのものだ。インストール不要、アカウント不要、アップロード不要で、構造パネル、ページ送りされた行、SQLエディタ、CSVエクスポートを提供する。その構造上ファイルに対して読み取り専用であるため、確認中のデータベースを壊す心配はない。

関連ツールと参考資料

データベースファイルと組み合わせて使うと相性のいい、ZeroTool上のツール。

  • CSV to SQL はCSVを CREATE TABLE と INSERT 文に変換する。新規のSQLiteファイルにテストデータを投入するのに使える。
  • SQL Formatter は、エディタに貼り付ける前に、長い CREATE 文やクエリを読みやすく整形する。
  • CSV ↔ JSON は、エクスポートしたクエリ結果をJSONに変換し、フィクスチャやAPIモックに使える。
  • JSON Formatter は、TEXTカラムに格納されたJSONドキュメントを扱う際に役立つ。

このガイドで参照した一次情報源。