CSV do SQL
Generuj instrukcje SQL INSERT z danych CSV
Wejście CSV
Wyjście SQL
Czym jest konwersja CSV do SQL?
Konwersja CSV do SQL przekształca wartości rozdzielone przecinkami w instrukcje języka SQL, które może wykonać relacyjna baza danych. Najczęstszym wynikiem jest para: instrukcja CREATE TABLE definiująca kolumny oraz jedna lub więcej instrukcji INSERT INTO, które wypełniają te kolumny wierszami z pliku CSV.
Pliki CSV stosują się do specyfikacji RFC 4180. Każda linia to jeden rekord, pola są oddzielone separatorem (zazwyczaj przecinkiem), a pola zawierające separator lub znaki nowej linii są ujmowane w podwójne cudzysłowy. SQL jest z kolei standardowym językiem zarządzania danymi w systemach takich jak PostgreSQL, MySQL, SQLite i SQL Server. Konwersja między tymi dwoma formatami to jedno z najczęstszych zadań importu danych w tworzeniu oprogramowania.
Porządny konwerter CSV-do-SQL obsługuje cytowanie, zmieniając apostrofy wewnątrz wartości na podwojone '' zgodnie ze standardem SQL, mapuje nagłówki kolumn na prawidłowe identyfikatory SQL i opcjonalnie może wnioskować typy danych. Oprócz podstawowego escapowania dobry konwerter normalizuje nazwy nagłówków (zastępując spacje i myślniki podkreślnikami) oraz opakowuje wynik w blok transakcji, dzięki czemu błąd importu cofa zmiany bez pozostawiania niepełnych danych w tabeli. Bez konwertera ręczne pisanie instrukcji INSERT nawet dla kilkuset wierszy jest podatne na błędy i czasochłonne.
Dlaczego warto używać konwertera CSV do SQL?
Ręczne pisanie instrukcji SQL INSERT z danych arkusza kalkulacyjnego jest żmudne i sprzyja błędom składniowym. Konwerter automatyzuje powtarzalne czynności, dzięki czemu możesz skupić się na projektowaniu schematu i walidacji danych.
Przypadki użycia konwertera CSV do SQL
Typy danych SQL — wykaz
Podczas konwersji CSV do SQL każda kolumna domyślnie otrzymuje typ TEXT, ponieważ CSV nie zawiera metadanych o typach. Jeśli znasz typy kolumn, możesz zastąpić TEXT w wygenerowanej instrukcji CREATE TABLE. Ta tabela przedstawia najczęstsze typy SQL i kiedy należy ich używać.
| Typ | Zastosowanie | Uwagi |
|---|---|---|
| TEXT / VARCHAR | Strings, mixed content | Default safe choice; works in every SQL dialect |
| INTEGER / INT | Whole numbers (age, count, ID) | Use when column contains only digits with no decimals |
| REAL / FLOAT | Decimal numbers (price, rate) | Needed for columns with dots like 19.99 or 3.14 |
| DATE | ISO 8601 dates (2024-01-15) | Requires consistent formatting; varies by database |
| BOOLEAN | true/false, 1/0, yes/no | MySQL uses TINYINT(1); PostgreSQL has native BOOL |
| NUMERIC / DECIMAL | Exact precision (currency) | Specify scale: DECIMAL(10,2) for money columns |
| BLOB / BYTEA | Binary data | Rarely needed in CSV imports; use for hex-encoded fields |
Porównanie dialektów SQL
Składnia SQL różni się między silnikami baz danych. Wygenerowane instrukcje INSERT używają standardowego SQL działającego w większości systemów, jednak niektóre funkcje się różnią. Ta tabela podsumowuje różnice najważniejsze przy imporcie danych CSV.
| Funkcja | PostgreSQL | MySQL | SQLite | SQL Server |
|---|---|---|---|---|
| Identifier quoting | "col" | `col` | "col" | [col] |
| String escape | '' | '' or \' | '' | '' |
| INSERT syntax | INSERT INTO | INSERT INTO | INSERT INTO | INSERT INTO |
| Batch INSERT | VALUES (),()… | VALUES (),()… | VALUES (),()… | max 1000 rows |
| Auto-increment | SERIAL | AUTO_INCREMENT | AUTOINCREMENT | IDENTITY(1,1) |
| Upsert / merge | ON CONFLICT | ON DUPLICATE KEY | ON CONFLICT | MERGE |
| NULL handling | IS NULL | IS NULL / <=> | IS NULL | IS NULL |
| COPY from CSV | COPY … FROM | LOAD DATA INFILE | .import | BULK INSERT |
INSERT vs COPY: wybór metody importu
W przypadku małych i średnich zestawów danych (poniżej 10 000 wierszy) instrukcje INSERT działają dobrze i są przenośne na każdą bazę danych SQL. Dla dużych importów bazy danych udostępniają polecenia masowego ładowania, które całkowicie omijają parser SQL.
Przykłady kodu
Te przykłady pokazują, jak konwertować CSV na instrukcje SQL INSERT w różnych językach programowania. Każdy z nich obsługuje escapowanie apostrofów i oczyszczanie nazw kolumn.
// 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');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');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');
}# 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;"