이 CSV SQL 변환기는 CSV나 TSV를 읽어 두 부분으로 된 스크립트를 만듭니다. 데이터를 보고 열 타입을 정한 CREATE TABLE과, 모든 레코드를 담은 여러 행 INSERT INTO ... VALUES 문입니다. PostgreSQL, MySQL, SQLite 중 하나를 고르면 식별자 따옴표, 타입 이름, 불리언 리터럴, 문자열 이스케이프가 그 데이터베이스 방식으로 바뀝니다. 테스트 DB 시딩, 작은 참조 테이블 적재, 스프레드시트 내보내기를 실행 전에 검토할 수 있는 마이그레이션으로 바꿀 때 씁니다.
타입은 열 단위로 정합니다. 기본으로 켜져 있는 ‘숫자·불리언·null 감지’에서는 채워진 셀이 모두 조건에 맞을 때만 숫자나 BOOLEAN 열이 되고, 나머지는 TEXT입니다. 빈 셀과 NA 같은 단어는 NULL이 되고, 02139 같은 우편번호나 20자리 ID는 TEXT로 남아 값이 몰래 망가지지 않습니다.
스크립트는 붙여 넣은 텍스트나 연 파일로 브라우저 안에서 만들어집니다. 입력한 내용은 브라우저 안에서 처리되며 서버로 전송되지 않고, 이 도구는 데이터베이스에 접속하지도 않습니다. 입력 한도는 20 MiB, 데이터 행 50,000개, 열 200개입니다.
사용 방법
CSV 붙여 넣기 또는 열기
행을 붙여 넣거나 .csv, .tsv 파일을 끌어다 놓거나 예제 하나로 시작합니다. 따옴표로 감싼 값에는 구분자, 두 번 쓴 따옴표, 줄바꿈이 들어가도 되고, 맨 앞의 UTF-8 BOM은 제거됩니다.
파일을 읽은 결과 확인
입력창 아래 배지에 ‘자동 감지’가 앞쪽 레코드를 보고 고른 구분자가 표시됩니다. 틀렸다면 ‘구분자’를 쉼표, 세미콜론, 탭, 파이프 중 하나로 지정하세요. ‘파일을 읽은 결과’ 패널에서 앞쪽 행과 열마다 정해진 타입을 볼 수 있습니다.
테이블 이름과 방언 정하기
테이블 이름(기본값
records)을 입력하고 PostgreSQL, MySQL, SQLite 중 하나를 고릅니다. 이름은 식별자 하나로 따옴표 처리되므로main.users가 아니라users만 입력하세요.타입과 NULL 처리 정하기
타입이 있는 열을 원하면 ‘숫자·불리언·null 감지’를 켜 두고, 내보낸 파일이 쓰는
-나missing같은 표시는 ‘null로 볼 단어’에 추가합니다. 감지를 끄면 모든 셀이 따옴표 문자열이 되고, 나중에 빈 값이 있는 행이 더 들어올 테이블이라면 ‘가능하면 NOT NULL’을 끄세요.안내를 읽고 복사 또는 다운로드
결과 아래 안내에 건너뛴 빈 줄, 셀 수가 다른 레코드, 이름이 바뀐 열, 텍스트로 남긴 숫자가 표시됩니다. 스크립트를 복사하거나 테이블 이름을 딴 .sql 파일로 내려받아 SQL 클라이언트에서 실행하세요.
작동 원리
열 타입을 정하는 방식
셀 하나가 아니라 열 전체가 타입을 정합니다. 숫자는 평범하게 쓰여 있어야 합니다. 부호(선택), 숫자, 소수부와 지수(선택)만 있고 천 단위 구분 기호와 앞자리 0이 없어야 합니다. 그래서 1e3과 -0.5는 숫자지만 1,250, $5, 007은 아닙니다. 또 JavaScript 숫자로 바꾼 값을 다시 출력했을 때 같은 십진수가 나와야 합니다. 20자리 12345678901234567890이나 0.1234567890123456789처럼 반올림되는 값이 있으면 열은 TEXT로 남고 안내에 이름이 표시됩니다. 채워진 셀이 하나도 없는 열은 NULL을 허용하는 TEXT 열이 됩니다.
값은 해석된 숫자로 쓰이므로 19.50은 19.5로, 1e3은 1000으로 들어갑니다. DECIMAL, DATE, TIMESTAMP는 만들어지지 않습니다. 날짜는 TEXT로 남고, 가격은 실행 전에 CREATE TABLE에서 타입을 바꾸지 않으면 이진 부동소수점 열에 들어갑니다.
| 열에 든 값 | PostgreSQL | MySQL | SQLite |
|---|---|---|---|
| 2,147,483,647 이하의 정수 | INTEGER | INT | INTEGER |
| 그보다 크고 2^63 미만인 정수 | BIGINT | BIGINT | INTEGER |
| 소수나 지수가 하나라도 있음 | DOUBLE PRECISION | DOUBLE | REAL |
| true / false만 있음 | BOOLEAN | BOOLEAN | INTEGER (1 / 0) |
| 그 밖의 값, 또는 값 없음 | TEXT | TEXT | TEXT |
방언별 따옴표와 이스케이프
테이블 이름과 모든 열 이름은 항상 따옴표로 감싸므로 공백, 대문자, order 같은 예약어가 든 헤더도 그대로 쓸 수 있습니다. PostgreSQL과 SQLite는 큰따옴표, MySQL은 백틱을 쓰고 이름 안의 따옴표 문자는 두 번 씁니다. 문자열 값은 ISO SQL 규칙대로 작은따옴표로 감싸고 안의 '를 두 번 씁니다. MySQL은 문자열 안의 역슬래시도 이스케이프 문자로 읽기 때문에 이 방언에서만 역슬래시를 두 개로 만들고, 역슬래시를 글자 그대로 읽는 PostgreSQL과 SQLite에는 그대로 넘깁니다.
불리언은 PostgreSQL과 MySQL에서 TRUE, FALSE, 불리언 타입이 없는 SQLite에서 1, 0이 됩니다. 값 안의 줄바꿈은 따옴표 리터럴 안에 그대로 남으며 세 데이터베이스 모두 이를 받아들입니다.
| CSV 셀 | PostgreSQL | MySQL | SQLite |
|---|---|---|---|
| O'Hara | 'O''Hara' | 'O''Hara' | 'O''Hara' |
| C:\temp | 'C:\temp' | 'C:\\temp' | 'C:\temp' |
| true | TRUE | TRUE | 1 |
| 빈 셀 또는 NA | NULL | NULL | NULL |
배치 단위와 NOT NULL 제약
레코드는 500행씩 INSERT 문 하나로 묶입니다. 50,000행 파일이면 거대한 문장 하나 대신 100개의 문장이 됩니다. 대부분의 클라이언트에서 패킷·문장 크기 한도에 걸리지 않고, 오류가 나도 어느 묶음인지 범위가 좁혀집니다.
‘가능하면 NOT NULL’이 켜져 있으면 이 파일에서 빈 셀이나 null 단어가 한 번도 없었던 열에만 NOT NULL이 붙습니다. 이는 변환한 샘플의 상태일 뿐 업무 규칙이 아니므로, 운영 테이블에 쓰기 전에 확인하세요.
실제 예시
id,customer,total,paid,note
1,O'Hara,19.50,true,Gift wrap
2,Bea Kim,7,false,NACREATE TABLE "orders" (
"id" INTEGER NOT NULL,
"customer" TEXT NOT NULL,
"total" DOUBLE PRECISION NOT NULL,
"paid" BOOLEAN NOT NULL,
"note" TEXT
);
INSERT INTO "orders" ("id", "customer", "total", "paid", "note") VALUES
(1, 'O''Hara', 19.5, TRUE, 'Gift wrap'),
(2, 'Bea Kim', 7, FALSE, NULL);테이블 이름 orders, 방언 PostgreSQL입니다. NA가 NULL이 되어 note 열만 NULL을 허용합니다. 19.50은 19.5로 쓰이고 아포스트로피는 두 번 쓰였습니다.
sku,path,price,in_stock
KB-100,C:\docs\kb.pdf,49.90,TRUE
MS-220,,19,falseCREATE TABLE `files` (
`sku` TEXT NOT NULL,
`path` TEXT,
`price` DOUBLE NOT NULL,
`in_stock` BOOLEAN NOT NULL
);
INSERT INTO `files` (`sku`, `path`, `price`, `in_stock`) VALUES
('KB-100', 'C:\\docs\\kb.pdf', 49.9, TRUE),
('MS-220', NULL, 19, FALSE);테이블 이름 files, 방언 MySQL입니다. 이름은 백틱으로 감싸고, MySQL용으로 역슬래시를 두 개로 만들었습니다. TRUE는 대소문자와 관계없이 인식되고 빈 path는 NULL이 됩니다.
order_id,zip,weight,gift
3000000001,02139,1.5,false
3000000002,10001,2,trueCREATE TABLE "shipments" (
"order_id" INTEGER NOT NULL,
"zip" TEXT NOT NULL,
"weight" REAL NOT NULL,
"gift" INTEGER NOT NULL
);
INSERT INTO "shipments" ("order_id", "zip", "weight", "gift") VALUES
(3000000001, '02139', 1.5, 0),
(3000000002, '10001', 2, 1);테이블 이름 shipments, 방언 SQLite입니다. zip은 앞자리 0을 지키려고 TEXT로 남고 안내에 이름이 표시됩니다. gift는 0과 1로 저장됩니다. 같은 order_id 열은 값이 2,147,483,647을 넘으므로 PostgreSQL에서는 BIGINT가 됩니다.
id,qty,note
1,,NA
2,3,okCREATE TABLE "items" (
"id" TEXT NOT NULL,
"qty" TEXT NOT NULL,
"note" TEXT NOT NULL
);
INSERT INTO "items" ("id", "qty", "note") VALUES
('1', '', 'NA'),
('2', '3', 'ok');테이블 이름 items, ‘숫자·불리언·null 감지’를 끈 상태입니다. 모든 열이 TEXT이고 빈 셀은 빈 문자열, NA는 텍스트로 남으므로 모든 열에 NOT NULL이 붙습니다.
id,name,name,
1,Ari,Kim,x
2,BeaCREATE TABLE "people" (
"id" INTEGER NOT NULL,
"name" TEXT NOT NULL,
"name_2" TEXT,
"column_4" TEXT
);
INSERT INTO "people" ("id", "name", "name_2", "column_4") VALUES
(1, 'Ari', 'Kim', 'x'),
(2, 'Bea', NULL, NULL);테이블 이름 people입니다. 열 목록에 같은 이름이 두 번 올 수 없으므로 반복된 헤더는 name_2, 빈 헤더는 column_4가 됐습니다. 짧은 두 번째 레코드는 NULL로 채워지고, 셀 수가 다른 레코드와 이름이 바뀐 열이 안내에 표시됩니다.
자주 하는 실수
소수점 쉼표는 텍스트로 남음
유럽식 스프레드시트에서 세미콜론으로 내보낸 파일에는
49,90같은 값이 흔합니다. 세미콜론 구분은 제대로 읽지만49,90은 평범한 숫자가 아니어서 열이 TEXT가 되고 값에 따옴표가 붙습니다. 내보내기 전에 소수점 기호를 바꾸거나 적재한 뒤 열을 변환하세요.금액이 부동소수점 열에 들어감
소수가 있는 열은 DOUBLE PRECISION, DOUBLE, REAL 같은 이진 부동소수점 타입이 됩니다. 가격이나 잔액이라면 실행 전에 CREATE TABLE에서
NUMERIC(12,2)나DECIMAL(12,2)로 바꾸세요.19.5같은 리터럴은 어느 쪽에도 들어갑니다.스키마가 붙은 테이블 이름
테이블 이름은 식별자 하나로 따옴표 처리되므로
main.users를 입력하면 main 스키마의 users가 아니라 이름에 점이 든"main.users"테이블이 만들어집니다. 테이블 이름만 입력하고 실행 전에 클라이언트에서 스키마나 데이터베이스를 선택하거나, 두 문장을 직접 고치세요.날짜는 텍스트로 들어감
2026-03-14는 TEXT 열에 들어갑니다. CREATE TABLE에서 그 열을 DATE로 바꾸면 PostgreSQL, MySQL, SQLite 모두 ISO 8601 문자열을 그대로 받아들이지만,03/14/2026같은 형식은 먼저 변환해야 합니다.NOT NULL은 이 파일 기준
이 CSV에서 우연히 빈 값이 없었던 열에도
NOT NULL이 붙습니다. 나중에 빈 값이 있는 다른 내보내기 파일을 넣으면 INSERT가 실패합니다. 데이터가 계속 들어올 테이블이라면 ‘가능하면 NOT NULL’을 끄세요.
자주 묻는 질문
테이블도 만들어 주나요?
네. 스크립트는 데이터에서 열 타입을 정한 CREATE TABLE로 시작하고 그 뒤에 INSERT 문이 이어집니다. 테이블이 이미 있다면 CREATE TABLE 부분만 지우세요. 각 INSERT의 열 목록이 헤더와 같으므로 INSERT는 그대로 동작합니다.
어떤 데이터베이스에서 실행되나요?
‘방언’에서 PostgreSQL, MySQL, SQLite를 고르면 그 데이터베이스의 식별자 따옴표, 타입 이름, 불리언 리터럴, 역슬래시 처리가 적용됩니다. MariaDB는 MySQL 출력을 받아들입니다. 다른 데이터베이스라면 표준 큰따옴표 식별자를 쓰는 PostgreSQL 출력에서 시작해 타입을 고치세요.
숫자 열이 왜 TEXT가 되나요?
채워진 셀 중 하나 이상이 조건에 맞지 않기 때문입니다. 앞자리 0, 천 단위 구분 기호, 통화 기호, 소수점 쉼표, JavaScript 숫자가 정확히 담지 못하는 긴 자릿수가 그렇습니다. 숫자처럼 보이지만 텍스트로 남은 열은 안내에 이름이 표시됩니다. ‘null로 볼 단어’에 없는 -나 missing 같은 표시가 하나만 있어도 열이 TEXT가 되니 목록에 추가하세요.
빈 셀은 어떻게 처리되나요?
감지가 켜져 있으면 빈 셀과 ‘null로 볼 단어’(기본값 NA, N/A, null, none, undefined, 대소문자 구분 없음)가 NULL이 됩니다. 감지를 끄면 빈 셀은 빈 문자열로 들어가고 그 단어들은 텍스트로 남습니다.
데이터 행을 추가하라는 오류가 나는 이유는?
열 타입을 레코드에서 배우기 때문에 헤더 행만 있는 파일로는 CREATE TABLE을 만들 수 없습니다. 데이터 행을 하나 이상 추가하거나, 첫 줄이 실제로 데이터라면 ‘첫 행은 헤더’를 끄세요. 그러면 열 이름이 column_1, column_2 식으로 붙습니다.
SQL 인젝션에 안전한가요?
모든 문자열은 작은따옴표 리터럴이고 안의 따옴표는 두 번 쓰며, MySQL에서는 역슬래시도 두 개로 만듭니다. 그래서 셀 내용이 리터럴을 닫고 SQL을 덧붙일 수 없습니다. 열 이름도 같은 방식으로 따옴표 처리됩니다. 그래도 운영 권한으로 실행하기 전에는 스크립트를 검토하세요.
CSV가 업로드되나요?
아니요. 입력한 내용은 브라우저 안에서 처리되며 서버로 전송되지 않고, 도구가 데이터베이스에 접속하는 일도 없습니다. 만들어진 스크립트는 사용하는 SQL 클라이언트에서 직접 실행합니다.
마지막 업데이트:
