CSVからSQL変換

CSVデータからSQL INSERT文を生成

サンプルを試す

CSV入力

SQL出力

ローカルで実行 · シークレットの貼り付けも安全
SQLがここに表示されます…
テーブル名:

CSVからSQLへの変換とは?

CSVからSQLへの変換は、カンマ区切りの値をリレーショナルデータベースが実行できる構造化クエリ言語(SQL)文に変換する処理です。最も一般的な出力は、カラムを定義するCREATE TABLE文と、CSVファイルの各行のデータをそれらのカラムに挿入する1つ以上のINSERT INTO文のペアです。

CSVファイルはRFC 4180仕様に従います。各行はレコードであり、フィールドは区切り文字(通常はカンマ)で分けられ、区切り文字や改行を含むフィールドはダブルクォートで囲まれます。一方SQLは、PostgreSQL、MySQL、SQLite、SQL Serverといったシステムでデータを管理するための標準言語です。この2つの形式間の変換は、ソフトウェア開発における最も頻繁なデータインポート作業のひとつです。

適切なCSV-to-SQLコンバーターはクォート処理を行い、値内のシングルクォートをエスケープし(SQLの標準に従って''に変換)、カラムヘッダーを有効なSQL識別子にマッピングし、オプションでデータ型を推論します。基本的なエスケープに加え、優れたコンバーターはヘッダー名を正規化し(スペースやハイフンをアンダースコアに置換)、出力をトランザクションブロックで囲むことで、インポートが失敗した際にテーブルに不完全なデータを残さずにロールバックできるようにします。コンバーターなしでは、数百行でもINSERT文を手書きすることはエラーが起きやすく非効率です。

CSVからSQLへの変換ツールを使う理由

スプレッドシートのデータからSQL INSERT文を手書きするのは手間がかかり、構文エラーが発生しやすいです。コンバーターは繰り返し作業を自動化するので、スキーマ設計とデータ検証に集中できます。

数秒でSQLを生成
CSVを貼り付けるだけで、すぐに実行できるSQL出力が得られます。文字列のクォート、アポストロフィのエスケープ、カラム数の確認を手動で行う必要はありません。変換処理はすべてブラウザ内で実行されます。
🔒
データはブラウザ内に保持
CSVはあなたのマシンの外に送信されることはありません。解析とSQL生成はすべてクライアントサイドで行われるため、サーバーへのアップロード、ログへの記録、第三者によるデータセットへのアクセスは一切ありません。
🎯
正確なSQL構文を生成
値内のシングルクォートはSQLの標準に従って''にエスケープされます。カラム名は有効な識別子に変換されます。出力はPostgreSQL、MySQL、SQLiteで構文的に有効です。
📋
あらゆるCSV構造に対応
ツールは区切り文字(カンマ、セミコロン、タブ、パイプ)を自動検出し、RFC 4180のルールに従って、カンマや改行を含むクォートされたフィールドを処理します。

CSVからSQL変換のユースケース

データベースシーディング
CSVのフィクスチャファイルを開発環境やステージング環境用のINSERT文に変換します。ORMを使わずに繰り返し可能なシードデータが必要なCIパイプラインで役立ちます。
データ移行
あるシステム(CRM、スプレッドシート、旧来のアプリケーション)からエクスポートしたデータを新しいリレーショナルデータベースに移動します。SQLを生成し、内容を確認してからトランザクション内で実行します。
バックエンドAPI開発
CSVからのテストデータでローカルのPostgreSQLまたはMySQLインスタンスを素早く準備します。一度だけのデータロードが必要な場合、マイグレーションスクリプトを書くよりも高速です。
QAとテスト自動化
CSVのテストフィクスチャからSQLを生成して、インテグレーションテスト前のデータベース状態を設定します。テスト実行の間にテーブルをリセットするためのティアダウンスクリプトと組み合わせて使用します。
データ分析の準備
CSVデータセットをSQLiteに読み込んでアドホッククエリを実行します。SQLiteはSQL INSERT文を直接読み込むため、スプレッドシートのエクスポートからクエリ可能なデータへの最速の手順です。
SQLの学習
学習者はサンプルCSVをSQLに変換することで、スキーマをゼロから設定することなく、実際のデータに対してSELECT、JOIN、集計クエリの練習ができます。

SQLデータ型リファレンス

CSVをSQLに変換する際、CSVには型のメタデータがないため、すべてのカラムはデフォルトでTEXTになります。カラムの型がわかっている場合は、CREATE TABLE出力のTEXTを置き換えることができます。この表は最も一般的なSQLの型とその使用場面を示しています。

用途備考
TEXT / VARCHARStrings, mixed contentDefault safe choice; works in every SQL dialect
INTEGER / INTWhole numbers (age, count, ID)Use when column contains only digits with no decimals
REAL / FLOATDecimal numbers (price, rate)Needed for columns with dots like 19.99 or 3.14
DATEISO 8601 dates (2024-01-15)Requires consistent formatting; varies by database
BOOLEANtrue/false, 1/0, yes/noMySQL uses TINYINT(1); PostgreSQL has native BOOL
NUMERIC / DECIMALExact precision (currency)Specify scale: DECIMAL(10,2) for money columns
BLOB / BYTEABinary dataRarely needed in CSV imports; use for hex-encoded fields

SQLダイアレクト比較

SQL構文はデータベースエンジンによって異なります。生成されるINSERT文はほとんどのシステムで動作する標準SQLを使用していますが、特定の機能は異なります。この表はCSVデータをインポートする際に最も重要な違いをまとめています。

機能PostgreSQLMySQLSQLiteSQL Server
Identifier quoting"col"`col`"col"[col]
String escape'''' or \'''''
INSERT syntaxINSERT INTOINSERT INTOINSERT INTOINSERT INTO
Batch INSERTVALUES (),()…VALUES (),()…VALUES (),()…max 1000 rows
Auto-incrementSERIALAUTO_INCREMENTAUTOINCREMENTIDENTITY(1,1)
Upsert / mergeON CONFLICTON DUPLICATE KEYON CONFLICTMERGE
NULL handlingIS NULLIS NULL / <=>IS NULLIS NULL
COPY from CSVCOPY … FROMLOAD DATA INFILE.importBULK INSERT

INSERT vs COPY:インポート方式の選択

小〜中規模のデータセット(1万行未満)では、INSERT文がうまく機能し、あらゆるSQLデータベース間で移植可能です。大規模なインポートでは、SQLパーサーを完全にバイパスするバルクロードコマンドがデータベースから提供されています。

INSERT INTO
標準SQL。あらゆる環境で動作します。各行はSQL文として解析されるため、大規模なデータセットではオーバーヘッドが大きくなります。条件付きロジック(ON CONFLICT、ON DUPLICATE KEY)をサポートします。シードデータ、小規模な移行、行レベルの制御が必要な場合に最適です。
COPY / LOAD DATA
データベース固有のバルクローダー。PostgreSQLはCOPY、MySQLはLOAD DATA INFILE、SQLiteは.import、SQL ServerはBULK INSERTを使用します。CSVを直接読み込み、SQLパーサーをスキップします。大規模ファイル(10万行以上)では10〜100倍高速です。サーバーまたはクライアントのファイルシステムへのアクセスが必要です。

コード例

これらの例は、異なるプログラミング言語でCSVをSQL INSERT文に変換する方法を示しています。それぞれシングルクォートのエスケープとカラム名の変換を処理しています。

JavaScript (Node.js)
// CSV → SQL INSERT statements
const csv = `name,age,city
Alice,30,Berlin
Bob,25,Tokyo`

function csvToSql(csv, table = 'data') {
  const rows = csv.trim().split('\n').map(r => r.split(','))
  const [headers, ...data] = rows
  const cols = headers.map(h => h.trim().toLowerCase().replace(/\s+/g, '_'))

  const values = data.map(row =>
    '  (' + row.map(v => `'${v.replace(/'/g, "''").trim()}'`).join(', ') + ')'
  )

  return `INSERT INTO ${table} (${cols.join(', ')}) VALUES
${values.join(',\n')};`
}

console.log(csvToSql(csv, 'users'))
// → INSERT INTO users (name, age, city) VALUES
//     ('Alice', '30', 'Berlin'),
//     ('Bob', '25', 'Tokyo');
Python
import csv
import io

csv_string = """name,age,city
Alice,30,Berlin
Bob,25,Tokyo"""

reader = csv.reader(io.StringIO(csv_string))
headers = [h.strip().lower().replace(' ', '_') for h in next(reader)]

table = 'users'
rows = list(reader)

# CREATE TABLE
col_defs = ', '.join(f'{h} TEXT' for h in headers)
print(f'CREATE TABLE {table} ({col_defs});')
# → CREATE TABLE users (name TEXT, age TEXT, city TEXT);

# INSERT statements
for row in rows:
    vals = ', '.join(f"'{v.replace(chr(39), chr(39)*2)}'" for v in row)
    print(f"INSERT INTO {table} ({', '.join(headers)}) VALUES ({vals});")
# → INSERT INTO users (name, age, city) VALUES ('Alice', '30', 'Berlin');
# → INSERT INTO users (name, age, city) VALUES ('Bob', '25', 'Tokyo');
Go
package main

import (
	"encoding/csv"
	"fmt"
	"strings"
)

func csvToSQL(data, table string) string {
	r := csv.NewReader(strings.NewReader(data))
	records, _ := r.ReadAll()
	if len(records) < 2 {
		return ""
	}

	headers := records[0]
	var vals []string
	for _, row := range records[1:] {
		escaped := make([]string, len(row))
		for i, v := range row {
			escaped[i] = "'" + strings.ReplaceAll(v, "'", "''") + "'"
		}
		vals = append(vals, "  ("+strings.Join(escaped, ", ")+")")
	}

	return fmt.Sprintf("INSERT INTO %s (%s) VALUES\n%s;",
		table, strings.Join(headers, ", "), strings.Join(vals, ",\n"))
}

func main() {
	csv := "name,age,city\nAlice,30,Berlin\nBob,25,Tokyo"
	fmt.Println(csvToSQL(csv, "users"))
	// → INSERT INTO users (name, age, city) VALUES
	//     ('Alice', '30', 'Berlin'),
	//     ('Bob', '25', 'Tokyo');
}
CLI (sqlite3 / psql)
# SQLite: import CSV directly into a table
sqlite3 mydb.db <<EOF
.mode csv
.import data.csv users
SELECT * FROM users LIMIT 5;
EOF

# PostgreSQL: COPY from CSV file (server-side)
psql -c "COPY users FROM '/path/to/data.csv' WITH (FORMAT csv, HEADER true);"

# PostgreSQL: \copy from CSV (client-side, no superuser needed)
psql -c "\copy users FROM 'data.csv' WITH (FORMAT csv, HEADER true);"

# MySQL: LOAD DATA from CSV
mysql -e "LOAD DATA INFILE '/path/to/data.csv' INTO TABLE users
  FIELDS TERMINATED BY ',' ENCLOSED BY '"'
  LINES TERMINATED BY '\n' IGNORE 1 ROWS;"

よくある質問

CSV値内のシングルクォートはSQL出力でどのように処理されますか?
CSV値内のすべてのシングルクォート(')はSQL出力で''に変換されます。これはSQLの標準エスケープシーケンスです。たとえば、「田中 O'Brien」という値はINSERT文で'田中 O''Brien'になります。この処理はPostgreSQL、MySQL、SQLite、SQL Serverで動作します。
MySQLやPostgreSQLなど特定のデータベース向けにCSVをSQLに変換できますか?
生成されるINSERT文は、MySQLとPostgreSQLの両方が受け付ける標準SQL構文を使用しています。主な違いは識別子のクォート方法です:PostgreSQLはダブルクォートを使用し、MySQLはバッククォートを使用します。基本的なINSERT操作については、出力はどちらでも変更なしに動作します。
CSVにヘッダー行がない場合はどうなりますか?
コンバーターは最初の行をカラムヘッダーとして扱います。CSVにヘッダーがない場合は、変換前にヘッダー行を追加してください。そうしないと、最初のデータ行がCREATE TABLE文のカラム名になります。このツールを含むほとんどのコンバーターはヘッダー行を必要とします。
CSVからSQLへの変換に行数の制限はありますか?
変換はブラウザ内で実行されるため、実際の制限はデバイスのメモリに依存します。数万行のファイルは問題なく変換できます。非常に大きなファイル(50万行以上)では、INSERT文の代わりにデータベース固有のCOPYまたはLOAD DATAコマンドの使用を検討してください。
なぜすべてのカラムの出力がINTEGERやDATEではなくTEXTになるのですか?
CSVは型のメタデータを持たないプレーンテキスト形式です。コンバーターは誤った型推論を避けるために、安全なデフォルトとしてTEXTを使用します。データを確認した後、生成されたCREATE TABLE文でカラムの型を変更できます。数値カラムにはINTEGER、日付カラムにはDATEが一般的な変更です。
セミコロンやタブを区切り文字とするCSVファイルはどのように扱えばよいですか?
このツールはCSVの最初の行を分析することで区切り文字を自動検出します。カンマ、セミコロン、タブ、パイプ文字を確認し、最も頻繁に出現するものを使用します。セミコロンを使用するヨーロッパ形式のCSVも設定変更なしに動作します。
生成されたSQLを直接実行してもインジェクションの危険はありませんか?
出力はシングルクォートをエスケープするため、偶発的な構文エラーを防ぎます。ただし、CSVデータが信頼できないソースからのものである場合は、生成されたSQLを未検証の入力と同様に扱ってください。本番データベースに対して実行する前に出力を確認してください。プログラムによるインポートには、文字列の結合よりもパラメーター化クエリの方が常に安全です。