CSV to SQL
SQL INSERT-statements genereren vanuit CSV-gegevens
CSV-invoer
SQL-uitvoer
Wat is CSV naar SQL-conversie?
CSV naar SQL-conversie zet kommagescheiden waarden om naar Structured Query Language-statements die een relationele database kan uitvoeren. De meest voorkomende uitvoer bestaat uit een tweetal: een CREATE TABLE-statement dat kolommen definieert, en een of meer INSERT INTO-statements die die kolommen vullen met de rijen uit het CSV-bestand.
CSV-bestanden volgen de RFC 4180-specificatie. Elke regel is een record, velden worden gescheiden door een scheidingsteken (doorgaans een komma), en velden die het scheidingsteken of regeleinden bevatten worden omsloten door dubbele aanhalingstekens. SQL daarentegen is de standaardtaal voor gegevensbeheer in systemen als PostgreSQL, MySQL, SQLite en SQL Server. Omzetten tussen deze twee formaten is een van de meest voorkomende gegevensimporttaken in softwareontwikkeling.
Een goede CSV-naar-SQL-converter handelt aanhalingstekens af, escapet enkele aanhalingstekens in waarden (door ze te verdubbelen naar '' conform de SQL-standaard), brengt kolomkoppen in kaart naar geldige SQL-identifiers en kan optioneel gegevenstypen afleiden. Naast basisescaping normaliseert een goede converter kopteksten (spaties en koppeltekens vervangen door underscores) en wikkelt de uitvoer in een transactieblok, zodat een mislukte import netjes teruggedraaid wordt in plaats van gedeeltelijke gegevens achter te laten in de tabel. Zonder converter is het handmatig schrijven van INSERT-statements voor zelfs een paar honderd rijen foutgevoelig en tijdrovend.
Waarom een CSV naar SQL-converter gebruiken?
SQL INSERT-statements handmatig schrijven vanuit spreadsheetgegevens is omslachtig en leidt tot syntaxfouten. Een converter automatiseert de repetitieve onderdelen zodat je je kunt richten op schemaontwerp en gegevensvalidatie.
Toepassingen van CSV naar SQL
Referentie SQL-gegevenstypen
Bij het omzetten van CSV naar SQL krijgt elke kolom standaard het type TEXT, omdat CSV geen typemetadata bevat. Als je de kolomtypen kent, kun je TEXT in de CREATE TABLE-uitvoer vervangen. Deze tabel toont de meest gebruikte SQL-typen en wanneer je ze toepast.
| Type | Gebruikt voor | Opmerkingen |
|---|---|---|
| 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 |
Vergelijking SQL-dialecten
SQL-syntaxis verschilt per database-engine. De gegenereerde INSERT-statements gebruiken standaard SQL die in de meeste systemen werkt, maar bepaalde functies wijken af. Deze tabel geeft een overzicht van de verschillen die het meest relevant zijn bij het importeren van CSV-gegevens.
| Functie | 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: een importmethode kiezen
Voor kleine tot middelgrote datasets (minder dan 10.000 rijen) werken INSERT-statements goed en zijn ze overdraagbaar naar elke SQL-database. Voor grote imports bieden databases bulklaadopdrachten die de SQL-parser volledig omzeilen.
Codevoorbeelden
Deze voorbeelden laten zien hoe je CSV omzet naar SQL INSERT-statements in verschillende programmeertalen. Elk voorbeeld verwerkt het escapen van enkele aanhalingstekens en het opschonen van kolomnamen.
// 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;"