ブラウザー内 SQL ワークベンチ
データ変換
読み込み中
ツールを読み込んでいます
ツールのコードは開いたときにのみ読み込まれます。
このツールの処理はすべてブラウザー内で行われ、入力内容はサーバーへ送信されません。
このツールについて
CSV またはフラットな JSON 配列を名前付きの一時テーブルに読み込み、実際の SQLite SQL で絞り込み、結合、集計、並べ替えを行います。CSV の値は先頭ゼロを含めて文字列のまま保持し、JSON の基本値は対応する数値・文字列・NULL として扱います。sql.js エンジンはローカルの Web Worker で動作します。入力のアップロード、データ内 URL へのアクセス、入力履歴の保存は行いません。同じ配信元に同梱した SQLite WASM は 658,410 バイト(約 643 KiB)で、別途 Worker JavaScript も使います。取得は明示的な読み込み操作の後だけです。テーブルはこのページの一時セッションにだけ存在します。対象は CSV・JSON の読み込みと参照クエリであり、SQLite データベースファイルや Parquet ファイルを開く機能は含みません。
主な用途
- 注文 CSV と顧客 JSON の参照表を LEFT JOIN で結合し、対応する顧客がない注文も確認する。
- エクスポートを絞り込み、数値文字列を明示的に変換し、部署や地域ごとに集計して確認後にダウンロードする。
- JSON の欠損値や文字列 ID を調べ、WITH 共通テーブル式で段階的なクエリを読みやすく記述する。
使い方
- 1.CSV または JSON を選び、一意のテーブル名を入力して、テキストを貼り付けるかローカルファイルを選び UTF-8・UTF-16LE・UTF-16BE を指定します。CSV はカンマ・セミコロン・タブ・縦線の区切りとヘッダーの有無を指定します。最大 8 件のソースを設定して一括読み込みし、各テーブルの列名と行数を確認します。無効なソースが一つでもあれば全体が失敗し、黙って除外することはありません。JSON はフラットなオブジェクト配列が必要で、入れ子のデータは先に別途変換してください。
- 2.表示されたテーブル名と列名を使い、必要なら WITH で始まる単一の SELECT を記述します。空白や記号を含む識別子は二重引用符で囲みます。CSV の数値は文字列なので、有効な数値であることを確認してから CAST を使います。順序を再現するには ORDER BY、結果を上限内に収めるには WHERE や LIMIT を加え、実行します。
- 3.CSV をダウンロードする前に、結果件数とページ分割されたプレビューを確認します。数式対策は既定で有効です。元の値で出力する場合は警告を読んで明示的に選択してください。出力対象は表示ページだけでなく、正常に得られた上限内の全結果です。キャンセルやリセットは Worker と全テーブルを破棄するため、続けるにはソースの再読み込みが必要です。
実行可能な CSV・JSON SQL の例
ID を保ったまま数値文字列を絞り込む
{
"sources": [
{
"name": "stock",
"format": "csv",
"text": "id,units\n001,12\n002,3\n010,20",
"delimiter": ",",
"header": true
}
],
"sql": "SELECT id, units FROM stock WHERE CAST(units AS INTEGER) >= 10 ORDER BY CAST(units AS INTEGER) DESC",
"safe": true
}{
"columns": [
"id",
"units"
],
"rows": [
[
"010",
"20"
],
[
"001",
"12"
]
]
}CAST が変えるのは比較方法であり、選択する id と units の文字列ではありません。ID は 010 と 001 のままで、明示的な ORDER BY が 20 を 12 より先にします。
JSON の真偽値・数値・欠損キーを読み込む
{
"sources": [
{
"name": "tickets",
"format": "json",
"text": "[{\"id\":\"T1\",\"open\":true,\"score\":4.5},{\"id\":\"T2\",\"open\":false,\"score\":null},{\"id\":\"T3\",\"open\":true}]",
"delimiter": ",",
"header": true
}
],
"sql": "SELECT id, open, score FROM tickets ORDER BY id",
"safe": true
}{
"columns": [
"id",
"open",
"score"
],
"rows": [
[
"T1",
1,
4.5
],
[
"T2",
0,
null
],
[
"T3",
1,
null
]
]
}JSON true/false は 1/0、4.5 は数値になります。明示的な null と存在しない score キーはどちらも SQL NULL です。文字列 ID は変わりません。
CSV を JSON 参照表に LEFT JOIN する
{
"sources": [
{
"name": "orders",
"format": "csv",
"text": "order_id,customer_id,total\nA100,001,12.50\nA101,002,0\nA102,009,7",
"delimiter": ",",
"header": true
},
{
"name": "customers",
"format": "json",
"text": "[{\"id\":\"001\",\"name\":\"Alice\"},{\"id\":\"002\",\"name\":\"ボブ\"}]",
"delimiter": ",",
"header": true
}
],
"sql": "SELECT o.order_id, c.name, o.total FROM orders AS o LEFT JOIN customers AS c ON o.customer_id = c.id ORDER BY o.order_id",
"safe": true
}{
"columns": [
"order_id",
"name",
"total"
],
"rows": [
[
"A100",
"Alice",
"12.50"
],
[
"A101",
"ボブ",
"0"
],
[
"A102",
null,
"7"
]
]
}顧客 ID は両ソースで文字列です。対応のない注文 A102 も顧客名 NULL で残り、元の total は文字列のままです。
検証済みの整数金額をグループ別に合計する
{
"sources": [
{
"name": "sales",
"format": "csv",
"text": "region,amount\nEast,10\nWest,7\nEast,20",
"delimiter": ",",
"header": true
}
],
"sql": "SELECT region, SUM(CAST(amount AS INTEGER)) AS total, COUNT(*) AS records FROM sales GROUP BY region ORDER BY region",
"safe": true
}{
"columns": [
"region",
"total",
"records"
],
"rows": [
[
"East",
30,
2
],
[
"West",
7,
1
]
]
}SUM の前に amount を明示的に整数へ変換します。East は 2 レコードで合計 30、West は 1 レコードで 7 です。この例は整数を使い、正確な十進演算を保証するものではありません。
WITH クエリで集計結果を絞り込む
{
"sources": [
{
"name": "sales",
"format": "csv",
"text": "region,amount\nEast,10\nWest,7\nEast,20",
"delimiter": ",",
"header": true
}
],
"sql": "WITH totals AS (SELECT region, SUM(CAST(amount AS INTEGER)) AS total FROM sales GROUP BY region) SELECT region, total FROM totals WHERE total >= 10 ORDER BY region",
"safe": true
}{
"columns": [
"region",
"total"
],
"rows": [
[
"East",
30
]
]
}共通テーブル式で地域別合計を求め、外側の SELECT で 10 以上だけを残します。WITH は単一の参照文の一部です。
元の表記を保ちながら数値順に並べる
{
"sources": [
{
"name": "items",
"format": "csv",
"text": "id,quantity\nA,10\nB,2\nC,001",
"delimiter": ",",
"header": true
}
],
"sql": "SELECT id, quantity, CAST(quantity AS INTEGER) AS numeric_quantity FROM items ORDER BY CAST(quantity AS INTEGER), id",
"safe": true
}{
"columns": [
"id",
"quantity",
"numeric_quantity"
],
"rows": [
[
"C",
"001",
1
],
[
"B",
"2",
2
],
[
"A",
"10",
10
]
]
}CAST で数値順と数値出力列を作ります。元の数量 001 はそのまま残り、数値としての解釈 1 を併記します。
空白や Unicode を含む識別子を引用する
{
"sources": [
{
"name": "商品",
"format": "csv",
"text": "名称,unit price\n猫,12.50",
"delimiter": ",",
"header": true
}
],
"sql": "SELECT \"名称\", \"unit price\" AS price FROM \"商品\"",
"safe": true
}{
"columns": [
"名称",
"price"
],
"rows": [
[
"猫",
"12.50"
]
]
}二重引用符はテーブル 商品 と列 unit price を識別します。猫 と価格文字列 12.50 は変わりません。単一引用符なら文字列リテラルになります。
引用された複数行 CSV フィールドを検索する
{
"sources": [
{
"name": "notes",
"format": "csv",
"text": "id,note\n001,\"first\nsecond\"\n002,\"comma, quote \"\"ok\"\"\"",
"delimiter": ",",
"header": true
}
],
"sql": "SELECT id, note FROM notes ORDER BY id",
"safe": true
}{
"columns": [
"id",
"note"
],
"rows": [
[
"001",
"first\nsecond"
],
[
"002",
"comma, quote \"ok\""
]
]
}CSV レコードの境界を正しく解釈します。最初のメモの改行は一つの値の一部で、二重に書かれた引用符は実際の引用符になります。
NULL と空文字を別々に数える
{
"sources": [
{
"name": "entries",
"format": "json",
"text": "[{\"id\":\"A\",\"value\":\"\"},{\"id\":\"B\",\"value\":null},{\"id\":\"C\"}]",
"delimiter": ",",
"header": true
}
],
"sql": "SELECT COUNT(*) AS records, COUNT(value) AS non_null, SUM(value IS NULL) AS nulls FROM entries",
"safe": true
}{
"columns": [
"records",
"non_null",
"nulls"
],
"rows": [
[
3,
1,
2
]
]
}全 3 行のうち、NULL ではない値は空文字の 1 件です。明示的な JSON null と欠損キーの両方が IS NULL に一致します。
ヘッダーなし CSV の自動列名を使う
{
"sources": [
{
"name": "people",
"format": "csv",
"text": "001;Paris\n002;東京",
"delimiter": ";",
"header": false
}
],
"sql": "SELECT column1 AS id, column2 AS city FROM people ORDER BY column1",
"safe": true
}{
"columns": [
"id",
"city"
],
"rows": [
[
"001",
"Paris"
],
[
"002",
"東京"
]
]
}ヘッダーを無効にし、セミコロンを指定すると両行がデータになります。列名は column1 と column2 になり、SELECT の別名で分かりやすい結果見出しを付けます。
数式に見えるヘッダーと値を既定で保護する
{
"sources": [
{
"name": "sheet",
"format": "csv",
"text": "note,total\n=1+1,-42\n@SUM(A1),0",
"delimiter": ",",
"header": true
}
],
"sql": "SELECT note AS \"=header\", total FROM sheet ORDER BY total",
"safe": true
}{
"columns": [
"=header",
"total"
],
"rows": [
[
"=1+1",
"-42"
],
[
"@SUM(A1)",
"0"
]
],
"csvRecords": [
[
"'=header",
"total"
],
[
"'=1+1",
"'-42"
],
[
"'@SUM(A1)",
"0"
]
]
}クエリ結果行は変わりません。csvRecords は =header、数式に見える文字列、-42 に出力時のアポストロフィが付くことを示します。CSV の通常の引用符だけでは数式を防げません。
信頼できる用途で元の値の CSV を明示的に選ぶ
{
"sources": [
{
"name": "sheet",
"format": "csv",
"text": "note,total\n=1+1,-42",
"delimiter": ",",
"header": true
}
],
"sql": "SELECT note AS \"=header\", total FROM sheet",
"safe": false
}{
"columns": [
"=header",
"total"
],
"rows": [
[
"=1+1",
"-42"
]
],
"csvRecords": [
[
"=header",
"total"
],
[
"=1+1",
"-42"
]
]
}safe が false なら csvRecords は結果とヘッダーの元の値に一致します。表計算ソフトで数式が実行される場合があるため、無対策の出力は慎重に選んでください。
ローカル SQL でよくある間違い
- CSV の数値文字列を、最初から数値型の列であるかのように比較・並べ替えする。
- CAST を検証の代わりに使い、不正な数値文字列を意図せずゼロに変換する。
- IS NULL の代わりに = NULL を使う、または COUNT(column) を全行数と考える。
- 一意でないキーを結合し、結果行が想定以上に増える。
- 列名を識別子用の二重引用符ではなく単一引用符で囲む。
- 入れ子や重複キーの JSON、または JavaScript の安全範囲外の整数を引用符なしで読み込む。
- キャンセル後もテーブルが残る、または上限超過で失敗したクエリを部分出力できると思い込む。
- 信頼できない無対策 CSV を表計算ソフトで開く、または CSV の引用符で数式を防げると考える。
制限と注意事項
- 各ソースは元ファイル 2 MiB、デコード後の UTF-8 テキスト 2 MiB、データ 10,000 行、128 列、200,000 セルまでです。セッションは最大 8 テーブル、元ソースの合計 8 MiB とデコード後の UTF-8 テキストの合計 8 MiB、50,000 行、500,000 セルです。テーブル名と列名は空白のみを不可とし、最大 128 UTF-8 バイトです。ASCII の大文字小文字だけが違う名前は重複扱いで、sqlite_ で始まるテーブル名は予約済みです。SQLite のネイティブ割り当ては 64 MiB、データベースページは 32 MiB が上限です。解析済み入力、JavaScript のコピー、Worker メッセージは別途メモリーを使うため、ブラウザー全体のヒープ上限ではありません。
- ファイルには UTF-8・UTF-16LE・UTF-16BE を明示的に指定し、不正なバイトや矛盾する BOM は拒否します。CSV は指定した区切りを使います。列数が不揃いの行、不正な引用符、空白または重複ヘッダーは読み込みエラーになります。区切りや旧来の文字コードの自動判別はしません。ヘッダーなしの列は column1、column2 などになります。CSV の値は空文字や数字に見える ID も TEXT のままです。値の暗黙変更を防ぐため、読み込むテキストの NUL 文字や不対の UTF-16 サロゲートは拒否します。JSON はフラットなオブジェクト配列を受け付け、キーを初出順に統合し、欠損と JSON null を SQL NULL、真偽値を 1/0 にします。入れ子、重複キー、安全範囲外の整数、精度を失う未対応の数値表記は拒否します。正確な ID や小数は引用符付き JSON 文字列にしてください。
- クエリは SQLite 構文の単一 SELECT または WITH…SELECT で、最大 20,000 UTF-8 バイトです。書き込み、PRAGMA、ATTACH、SQL 拡張、ファイル・ネットワークアクセス、バインドパラメーター、複数文は使えません。結果は最大 1,000 行、128 列、50,000 セル、合計 2 MiB、1 セル 256 KiB です。どれかを超えるとクエリ全体が失敗し、部分結果や出力は残りません。WHERE を絞る、選択列を減らす、LIMIT を付けるなどで調整してください。プレビューは 1 ページ 25 行、最大 12 列、1 セル 500 文字です。正常な出力には上限内の全結果が含まれます。
- 変換と比較は SQLite の規則に従います。無効な数値文字列が CAST でゼロになる場合があり、符号付き 64 ビット範囲外の INTEGER 変換は端の値に飽和するため、計算前に値を検証してください。小数演算は二進浮動小数点であり、正確な十進会計計算ではありません。JavaScript の安全整数範囲を超える 64 ビット整数の結果は正確な十進文字列で表します。BLOB の結果は生バイトではなく大文字の X'hex' テキストとして表示・出力します。ORDER BY がなければ行順は保証されません。結合キーの重複は行数を増やします。LIMIT は返す行数を制限しますが、低負荷なクエリを保証しません。
- CSV 出力は最大 6 MiB、UTF-8、カンマ区切り、引用符付きフィールド、CRLF のレコード区切りで、sql-result.csv としてダウンロードします。SQL NULL は空フィールドになり、空文字との違いが失われます。数式対策は負数を含む危険なヘッダーや値にアポストロフィを付け、意図的に出力値を変えます。表計算ソフトのすべての解釈を防ぐものではなく、無対策の CSV は数式実行や ID 変換につながる場合があります。各読み込み・クエリ・ページ取得・出力の制限時間は 10 秒です。キャンセル、タイムアウト、Worker 障害、ソース編集、リセット、画面移動ですべてのテーブルと結果を破棄しますが、個人情報を含む可能性のあるダウンロードは端末に残ります。このツールはデータベースファイル、外部拡張、リモートテーブル、保存されたクエリ履歴を作成しません。
よくある質問
CSV の ORDER BY で 10 が 2 より先になるのはなぜですか?
001 などの ID の元の表記を保つため、CSV 列は文字列として読み込みます。文字列の順序は文字単位で比較します。検証済みの数値なら ORDER BY CAST(quantity AS INTEGER) や CAST(amount AS REAL) を使えます。元の表記が重要なら SELECT に元の列も残してください。CAST は検証処理ではなく、不正な数値文字列がゼロになる場合があります。
CSV の空フィールドと JSON null はどう違いますか?
CSV の空フィールドは空文字列です。JSON null とオブジェクトに存在しないキーは SQL NULL になり、true と false は 1 と 0 になります。= NULL ではなく IS NULL を使ってください。COUNT(column) は NULL を除外し、COUNT(*) は行を数えます。CSV 出力では NULL も空文字も空フィールドになるため、ダウンロード後には区別できません。
テーブルの変更、データベースファイル、SQL パラメーターは使えますか?
読み込み操作でローカルの一時テーブルを作成しますが、入力 SQL は単一の参照クエリに制限されます。上限内で SELECT、結合、集計、WITH…SELECT に対応します。INSERT、UPDATE、DELETE、CREATE、DROP、PRAGMA、ATTACH、バインドパラメーター、拡張読み込みは拒否します。SQLite データベースファイルや Parquet ファイルは開けません。また SQLite SQL は他のすべてのデータベース方言と互換ではありません。
キャンセルした場合や結果が大きすぎる場合はどうなりますか?
キャンセルは Worker を終了し、実行中クエリだけでなく一時データベースと全テーブルを解放します。リセットや画面移動でもセッションを破棄するため、続けるには再読み込みが必要です。結果が行・列・セル・バイトの上限を超えると、部分ダウンロードを出さずに失敗します。絞り込み、選択列の削減、明示的な LIMIT を使ってください。プレビューだけの省略は、正常な出力を短くしません。