sqlite
SQLiteデータベースのコマンドやクエリ、組み込みデータベースのパターンを扱う際に活用するSkill。
📜 元の英語説明(参考)
SQLite database commands, queries, and embedded database patterns. Use when user mentions "sqlite", "sqlite3", "embedded database", "local database", "lightweight db", "sqlite schema", "sqlite backup", "mobile database", or working with .db/.sqlite files.
🇯🇵 日本人クリエイター向け解説
SQLiteデータベースのコマンドやクエリ、組み込みデータベースのパターンを扱う際に活用するSkill。
※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o sqlite.zip https://jpskill.com/download/6128.zip && unzip -o sqlite.zip && rm sqlite.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/6128.zip -OutFile "$d\sqlite.zip"; Expand-Archive "$d\sqlite.zip" -DestinationPath $d -Force; ri "$d\sqlite.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
sqlite.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
sqliteフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-17
- 取得日時
- 2026-05-17
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
SQLite
sqlite3 CLI の基本
sqlite3 myapp.db # データベースを開く、または作成する
sqlite3 :memory: # インメモリデータベース
sqlite3 myapp.db ".tables" # ワンショットコマンド
sqlite3 myapp.db < schema.sql # ファイルから SQL を実行する
シェル内でよく使うドットコマンドです。
.tables -- すべてのテーブルを一覧表示する
.schema -- すべてのテーブルの CREATE ステートメントを表示する
.schema users -- 特定のテーブルの CREATE ステートメントを表示する
.headers on -- 出力に列ヘッダーを表示する
.mode column -- 列を揃える (他に: csv, json, table, line, tabs)
.width 20 30 10 -- column モードの列幅を設定する
.databases -- 接続されているデータベースを一覧表示する
.indexes users -- テーブルのインデックスを一覧表示する
.quit -- 終了する
テーブルの作成、挿入、更新、削除
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY, -- rowid のエイリアス、自動インクリメント
name TEXT NOT NULL,
email TEXT UNIQUE,
created_at TEXT DEFAULT (datetime('now'))
);
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id),
total REAL NOT NULL,
status TEXT DEFAULT 'pending',
created_at TEXT DEFAULT (datetime('now'))
);
INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com');
INSERT INTO orders (user_id, total, status)
VALUES (1, 49.99, 'completed'), (1, 25.00, 'pending'), (2, 120.00, 'completed');
UPDATE users SET email = 'newalice@example.com' WHERE id = 1;
DELETE FROM orders WHERE status = 'pending' AND created_at < datetime('now', '-30 days');
RETURNING 句は 3.35.0 以降で利用可能です。sqlite3 --version で確認してください。
クエリ
JOIN、サブクエリ、GROUP BY
SELECT o.id, u.name, o.total
FROM orders o
JOIN users u ON u.id = o.user_id
WHERE o.status = 'completed';
SELECT u.name, COALESCE(SUM(o.total), 0) AS lifetime_value
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
GROUP BY u.name;
SELECT * FROM users
WHERE id IN (
SELECT user_id FROM orders GROUP BY user_id HAVING SUM(total) > 100
);
SELECT status, COUNT(*) AS cnt, ROUND(AVG(total), 2) AS avg_total
FROM orders GROUP BY status HAVING cnt > 1 ORDER BY avg_total DESC;
CTE とウィンドウ関数
WITH monthly AS (
SELECT strftime('%Y-%m', created_at) AS month, SUM(total) AS revenue
FROM orders WHERE status = 'completed' GROUP BY 1
)
SELECT month, revenue,
revenue - LAG(revenue) OVER (ORDER BY month) AS change
FROM monthly;
SELECT user_id, total,
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY total DESC) AS rn,
SUM(total) OVER (PARTITION BY user_id) AS user_total
FROM orders;
出力モード
sqlite3 -header -csv myapp.db "SELECT * FROM users;" > users.csv
sqlite3 -json myapp.db "SELECT * FROM users;"
sqlite3 -header -column myapp.db "SELECT * FROM users;"
シェル内では以下のようにします。
.mode csv -- カンマ区切り
.mode json -- オブジェクトの JSON 配列
.mode column -- 列を揃える
.mode table -- ASCII テーブルの罫線 (3.36 以降)
.mode line -- 1 行に 1 つの値
.separator "\t" -- list モードのカスタム区切り文字
CSV のインポートとエクスポート
# エクスポート
sqlite3 -header -csv myapp.db "SELECT * FROM users;" > users.csv
# 既存のテーブルにインポート
sqlite3 myapp.db <<'EOF'
.mode csv
.import users.csv users
EOF
大量のインポートの場合は、速度のためにトランザクションで囲みます。
BEGIN;
.mode csv
.import large_file.csv target_table
COMMIT;
インデックスと EXPLAIN QUERY PLAN
CREATE INDEX idx_orders_user ON orders(user_id);
CREATE INDEX idx_orders_status_date ON orders(status, created_at);
CREATE UNIQUE INDEX idx_users_email ON users(email);
EXPLAIN QUERY PLAN SELECT * FROM orders WHERE user_id = 1;
出力の重要な点です。
- SCAN TABLE -- 利用可能なインデックスがなく、すべての行を読み取ります
- SEARCH TABLE ... USING INDEX -- インデックスが使用されています
- USING COVERING INDEX -- クエリがインデックスから完全に回答されています
- USE TEMP B-TREE -- インデックスなしでソートまたは GROUP BY
WAL モードと同時実行性
PRAGMA journal_mode=WAL; -- 成功すると "wal" を返します
PRAGMA busy_timeout=5000; -- すぐに失敗する代わりに最大 5 秒待機します
- 一度に 1 つのライターですが、リーダーはブロックされません
- データベースの横に
-walおよび-shmファイルを作成します - チェックポイントを強制する:
PRAGMA wal_checkpoint(TRUNCATE); - 一度設定すると、接続間で永続化されます
バックアップ
.backup main backup.db -- オンラインバックアップ (使用中に安全)
.dump -- 完全な SQL テキストダンプ
.dump users -- 単一のテーブルをダンプする
sqlite3 myapp.db .dump > full_dump.sql # ファイルにダンプする
sqlite3 restored.db < full_dump.sql # ダンプから復元する
VACUUM はデータベースファイルを再構築し、スペースを再利用します。
VACUUM; -- その場で再構築する
VACUUM INTO 'compact.db'; -- 圧縮されたコピー (3.27 以降)
JSON サポート
SQLite 3.38 以降 (組み込み) または JSON1 拡張機能で利用可能です。
CREATE TABLE events (id INTEGER PRIMARY KEY, data TEXT NOT NULL);
INSERT INTO events (data)
VALUES ('{"type":"click","page":"/home","tags":["mobile","v2"]}');
-- 値を抽出する
SELECT json_extract(data, '$.type') AS event_type FROM events;
SELECT data->>'$.page' AS page FROM events; -- ->> 演算子 (3.38 以降)
-- 配列を反復処理する
SELECT e.id, j.value AS tag
FROM events e, json_each(json_extract(e.data, '$.tags')) j;
-- JSON を変更する
UPDATE events SET data = json_set(data, '$.processed', true) WHERE id = 1;
-- クエリで JSON を構築する
SELECT json_object('id', id, 'name', name) FROM users;
SELECT json_group_array(json_object('id', id, 'name', name)) FROM users;
全文検索 (FTS5)
CREATE VIRTUAL TABLE articles_fts USING fts5(title, body, content=articles, content_rowid=id);
-- 既存のテーブルからデータを投入する
INSERT INTO articles_fts(rowid, title, body) SELECT id, title, body FROM articles;
-- 論理演算子で検索する
SELECT *, rank FRO 📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
SQLite
sqlite3 CLI Basics
sqlite3 myapp.db # open or create a database
sqlite3 :memory: # in-memory database
sqlite3 myapp.db ".tables" # one-shot command
sqlite3 myapp.db < schema.sql # run SQL from file
Common dot-commands inside the shell:
.tables -- list all tables
.schema -- show CREATE statements for all tables
.schema users -- show CREATE for specific table
.headers on -- show column headers in output
.mode column -- aligned columns (also: csv, json, table, line, tabs)
.width 20 30 10 -- set column widths for column mode
.databases -- list attached databases
.indexes users -- list indexes for a table
.quit -- exit
Create Tables, Insert, Update, Delete
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY, -- alias for rowid, auto-increments
name TEXT NOT NULL,
email TEXT UNIQUE,
created_at TEXT DEFAULT (datetime('now'))
);
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id),
total REAL NOT NULL,
status TEXT DEFAULT 'pending',
created_at TEXT DEFAULT (datetime('now'))
);
INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com');
INSERT INTO orders (user_id, total, status)
VALUES (1, 49.99, 'completed'), (1, 25.00, 'pending'), (2, 120.00, 'completed');
UPDATE users SET email = 'newalice@example.com' WHERE id = 1;
DELETE FROM orders WHERE status = 'pending' AND created_at < datetime('now', '-30 days');
RETURNING clause available in 3.35.0+. Check with sqlite3 --version.
Queries
Joins, Subqueries, GROUP BY
SELECT o.id, u.name, o.total
FROM orders o
JOIN users u ON u.id = o.user_id
WHERE o.status = 'completed';
SELECT u.name, COALESCE(SUM(o.total), 0) AS lifetime_value
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
GROUP BY u.name;
SELECT * FROM users
WHERE id IN (
SELECT user_id FROM orders GROUP BY user_id HAVING SUM(total) > 100
);
SELECT status, COUNT(*) AS cnt, ROUND(AVG(total), 2) AS avg_total
FROM orders GROUP BY status HAVING cnt > 1 ORDER BY avg_total DESC;
CTEs and Window Functions
WITH monthly AS (
SELECT strftime('%Y-%m', created_at) AS month, SUM(total) AS revenue
FROM orders WHERE status = 'completed' GROUP BY 1
)
SELECT month, revenue,
revenue - LAG(revenue) OVER (ORDER BY month) AS change
FROM monthly;
SELECT user_id, total,
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY total DESC) AS rn,
SUM(total) OVER (PARTITION BY user_id) AS user_total
FROM orders;
Output Modes
sqlite3 -header -csv myapp.db "SELECT * FROM users;" > users.csv
sqlite3 -json myapp.db "SELECT * FROM users;"
sqlite3 -header -column myapp.db "SELECT * FROM users;"
Inside the shell:
.mode csv -- comma-separated
.mode json -- JSON array of objects
.mode column -- aligned columns
.mode table -- ASCII table borders (3.36+)
.mode line -- one value per line
.separator "\t" -- custom separator for list mode
Import and Export CSV
# Export
sqlite3 -header -csv myapp.db "SELECT * FROM users;" > users.csv
# Import into existing table
sqlite3 myapp.db <<'EOF'
.mode csv
.import users.csv users
EOF
For large imports, wrap in a transaction for speed:
BEGIN;
.mode csv
.import large_file.csv target_table
COMMIT;
Indexes and EXPLAIN QUERY PLAN
CREATE INDEX idx_orders_user ON orders(user_id);
CREATE INDEX idx_orders_status_date ON orders(status, created_at);
CREATE UNIQUE INDEX idx_users_email ON users(email);
EXPLAIN QUERY PLAN SELECT * FROM orders WHERE user_id = 1;
Key things in the output:
- SCAN TABLE -- no usable index, reads every row
- SEARCH TABLE ... USING INDEX -- index is being used
- USING COVERING INDEX -- query answered entirely from index
- USE TEMP B-TREE -- sort or GROUP BY without index
WAL Mode and Concurrency
PRAGMA journal_mode=WAL; -- returns "wal" on success
PRAGMA busy_timeout=5000; -- wait up to 5s instead of failing immediately
- One writer at a time, but readers are not blocked
- Creates
-waland-shmfiles alongside the database - Force checkpoint:
PRAGMA wal_checkpoint(TRUNCATE); - Set once; persists across connections
Backup
.backup main backup.db -- online backup (safe during use)
.dump -- full SQL text dump
.dump users -- dump a single table
sqlite3 myapp.db .dump > full_dump.sql # dump to file
sqlite3 restored.db < full_dump.sql # restore from dump
VACUUM rebuilds the database file, reclaiming space:
VACUUM; -- rebuild in place
VACUUM INTO 'compact.db'; -- compacted copy (3.27+)
JSON Support
Available in SQLite 3.38+ (built-in) or via the JSON1 extension:
CREATE TABLE events (id INTEGER PRIMARY KEY, data TEXT NOT NULL);
INSERT INTO events (data)
VALUES ('{"type":"click","page":"/home","tags":["mobile","v2"]}');
-- Extract values
SELECT json_extract(data, '$.type') AS event_type FROM events;
SELECT data->>'$.page' AS page FROM events; -- ->> operator (3.38+)
-- Iterate over arrays
SELECT e.id, j.value AS tag
FROM events e, json_each(json_extract(e.data, '$.tags')) j;
-- Modify JSON
UPDATE events SET data = json_set(data, '$.processed', true) WHERE id = 1;
-- Build JSON in queries
SELECT json_object('id', id, 'name', name) FROM users;
SELECT json_group_array(json_object('id', id, 'name', name)) FROM users;
Full-Text Search (FTS5)
CREATE VIRTUAL TABLE articles_fts USING fts5(title, body, content=articles, content_rowid=id);
-- Populate from existing table
INSERT INTO articles_fts(rowid, title, body) SELECT id, title, body FROM articles;
-- Search with boolean operators
SELECT *, rank FROM articles_fts WHERE articles_fts MATCH 'database AND performance' ORDER BY rank;
-- Highlight matches
SELECT highlight(articles_fts, 1, '<b>', '</b>') FROM articles_fts WHERE articles_fts MATCH 'sqlite';
-- Keep in sync with triggers
CREATE TRIGGER articles_ai AFTER INSERT ON articles BEGIN
INSERT INTO articles_fts(rowid, title, body) VALUES (new.id, new.title, new.body);
END;
CREATE TRIGGER articles_ad AFTER DELETE ON articles BEGIN
INSERT INTO articles_fts(articles_fts, rowid, title, body)
VALUES ('delete', old.id, old.title, old.body);
END;
Date and Time Functions
SQLite stores dates as TEXT, REAL, or INTEGER. Built-in functions handle ISO-8601 strings:
SELECT datetime('now'); -- 2025-01-15 08:30:00
SELECT date('now', '-7 days'); -- 7 days ago
SELECT strftime('%Y-%m', 'now'); -- current year-month
SELECT strftime('%s', 'now'); -- unix timestamp
SELECT datetime('2025-01-15', '+3 months', '-1 day'); -- date arithmetic
SELECT julianday('now') - julianday(created_at) AS days_old FROM users;
Attach Multiple Databases
ATTACH DATABASE 'archive.db' AS archive;
SELECT * FROM main.users u JOIN archive.orders o ON o.user_id = u.id;
INSERT INTO archive.orders SELECT * FROM main.orders WHERE created_at < '2024-01-01';
DELETE FROM main.orders WHERE created_at < '2024-01-01';
DETACH DATABASE archive;
Pragmas
-- Performance
PRAGMA journal_mode=WAL;
PRAGMA synchronous=NORMAL; -- faster writes (safe with WAL)
PRAGMA cache_size=-64000; -- 64MB page cache (negative = KB)
PRAGMA mmap_size=268435456; -- memory-map up to 256MB
PRAGMA temp_store=MEMORY; -- temp tables in memory
-- Integrity
PRAGMA foreign_keys=ON; -- enforce foreign keys (off by default!)
PRAGMA integrity_check; -- full database integrity scan
-- Info
PRAGMA table_info(users); -- column details
PRAGMA index_list(users); -- indexes on a table
PRAGMA compile_options; -- build-time options (check for JSON, FTS5)
Common Patterns
Config Key-Value Store
CREATE TABLE config (
key TEXT PRIMARY KEY, value TEXT,
updated_at TEXT DEFAULT (datetime('now'))
);
INSERT OR REPLACE INTO config (key, value) VALUES ('theme', 'dark');
SELECT value FROM config WHERE key = 'theme';
Local Cache with Expiry
CREATE TABLE cache (key TEXT PRIMARY KEY, value TEXT, expires_at TEXT);
INSERT OR REPLACE INTO cache (key, value, expires_at)
VALUES ('api:/users', '{"data":[...]}', datetime('now', '+1 hour'));
SELECT value FROM cache WHERE key = 'api:/users' AND expires_at > datetime('now');
DELETE FROM cache WHERE expires_at <= datetime('now');
CLI Tool Storage
CREATE TABLE history (
id INTEGER PRIMARY KEY, command TEXT NOT NULL,
args TEXT, exit_code INTEGER,
ran_at TEXT DEFAULT (datetime('now'))
);
SELECT command, args, ran_at FROM history ORDER BY ran_at DESC LIMIT 20;
SELECT command, COUNT(*) AS cnt FROM history GROUP BY command ORDER BY cnt DESC;
Test Fixtures
sqlite3 test.db < schema.sql && sqlite3 test.db < seed.sql
# In-memory: Python sqlite3.connect(":memory:") / Node new Database(":memory:")
BEGIN;
INSERT INTO users (id, name, email) VALUES
(1, 'Test User', 'test@example.com'),
(2, 'Admin', 'admin@example.com');
INSERT INTO orders (user_id, total, status) VALUES
(1, 99.99, 'completed'), (2, 50.00, 'pending');
COMMIT;