CSV to SQL 변환기

CSV 데이터에서 SQL INSERT 문 생성

예시 시도

CSV 입력

SQL 출력

로컬에서 실행 · 시크릿 붙여넣기 안전
SQL이 여기에 표시됩니다…
테이블 이름:

CSV to SQL 변환이란?

CSV to SQL 변환은 쉼표로 구분된 값을 관계형 데이터베이스가 실행할 수 있는 SQL 문으로 변환합니다. 가장 일반적인 출력은 한 쌍으로 구성됩니다. 열을 정의하는 CREATE TABLE 문과, CSV 파일의 행으로 해당 열을 채우는 하나 이상의 INSERT INTO 문입니다.

CSV 파일은 RFC 4180 명세를 따릅니다. 각 줄은 하나의 레코드이며, 필드는 구분자(일반적으로 쉼표)로 분리되고, 구분자나 줄바꿈을 포함하는 필드는 큰따옴표로 감쌉니다. SQL은 PostgreSQL, MySQL, SQLite, SQL Server 같은 시스템에서 데이터를 관리하는 표준 언어입니다. 이 두 형식 간 변환은 소프트웨어 개발에서 가장 빈번한 데이터 가져오기 작업 중 하나입니다.

올바른 CSV-to-SQL 변환기는 인용을 처리하고, 값 내의 작은따옴표를 이스케이프하며(SQL 표준에 따라 ''로 두 배 처리), 열 헤더를 유효한 SQL 식별자에 매핑하고, 선택적으로 데이터 타입을 추론할 수 있습니다. 기본 이스케이프 처리 외에도 좋은 변환기는 헤더 이름을 정규화하고(공백과 하이픈을 밑줄로 교체), 출력을 트랜잭션 블록으로 감싸서 가져오기 실패 시 부분 데이터가 테이블에 남지 않고 깔끔하게 롤백되도록 합니다. 변환기 없이 수백 행의 INSERT 문을 직접 작성하는 것은 오류가 발생하기 쉽고 느립니다.

CSV to SQL 변환기를 사용하는 이유

스프레드시트 데이터에서 SQL INSERT 문을 직접 작성하는 것은 번거롭고 구문 오류를 유발합니다. 변환기는 반복적인 부분을 자동화하여 스키마 설계와 데이터 유효성 검사에 집중할 수 있게 해줍니다.

몇 초 만에 SQL 생성
CSV를 붙여넣으면 바로 실행 가능한 SQL 출력을 얻습니다. 문자열에 직접 따옴표를 붙이거나, 아포스트로피를 이스케이프하거나, 열 수를 세는 작업이 필요 없습니다. 변환은 브라우저에서 완전히 실행됩니다.
🔒
데이터는 브라우저 안에 유지
CSV는 절대 사용자의 기기를 벗어나지 않습니다. 모든 파싱과 SQL 생성은 클라이언트 측에서 이루어지므로 서버 업로드, 로깅, 제3자의 데이터셋 접근이 없습니다.
🎯
올바른 SQL 구문 생성
값 내의 작은따옴표는 SQL 표준에 따라 ''로 이스케이프됩니다. 열 이름은 유효한 식별자로 정제됩니다. 출력은 PostgreSQL, MySQL, SQLite에서 구문적으로 유효합니다.
📋
모든 CSV 구조 처리
이 도구는 구분자(쉼표, 세미콜론, 탭, 파이프)를 자동 감지하고, RFC 4180 규칙에 따라 쉼표나 줄바꿈이 내포된 따옴표 필드를 처리합니다.

CSV to 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: 가져오기 방법 선택

소규모에서 중규모 데이터셋(10,000행 미만)의 경우 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를 사용합니다. SQL 파서를 건너뛰고 CSV를 직접 읽습니다. 대용량 파일(100K행 이상)에서 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 to SQL 변환의 행 수 제한이 있나요?
변환이 브라우저에서 실행되므로 실질적인 한계는 기기의 메모리에 따라 다릅니다. 수만 행의 파일도 문제없이 변환됩니다. 매우 큰 파일(50만 행 이상)의 경우 INSERT 문 대신 데이터베이스의 기본 COPY 또는 LOAD DATA 명령을 사용하는 것을 권장합니다.
출력이 INTEGER나 DATE 대신 모든 열에 TEXT를 사용하는 이유는 무엇인가요?
CSV는 타입 메타데이터가 없는 일반 텍스트 형식입니다. 변환기는 잘못된 타입 추론을 방지하기 위해 안전한 기본값으로 TEXT를 사용합니다. 데이터를 검토한 후 생성된 CREATE TABLE 문에서 열 타입을 변경할 수 있습니다. 숫자 열에는 INTEGER, 날짜 열에는 DATE가 일반적인 조정입니다.
구분자로 세미콜론이나 탭을 사용하는 CSV 파일은 어떻게 처리해야 하나요?
이 도구는 CSV의 첫 번째 행을 분석하여 구분자를 자동 감지합니다. 쉼표, 세미콜론, 탭, 파이프 문자를 확인하고 가장 자주 나타나는 것을 사용합니다. 세미콜론을 사용하는 유럽 형식 CSV도 별도의 설정 변경 없이 작동합니다.
생성된 SQL을 직접 실행해도 인젝션으로부터 안전한가요?
출력은 작은따옴표를 이스케이프하여 우발적인 구문 오류를 방지합니다. 그러나 CSV 데이터가 신뢰할 수 없는 출처에서 온 경우, 생성된 SQL을 검증되지 않은 입력과 동일하게 취급하세요. 프로덕션 데이터베이스에서 실행하기 전에 출력을 검토하세요. 프로그래밍 방식의 가져오기에는 문자열 연결보다 매개변수화된 쿼리가 항상 더 안전합니다.