CSV to SQL
SQL INSERT-Statements aus CSV-Daten generieren
CSV-Eingabe
SQL-Ausgabe
Was ist CSV-zu-SQL-Konvertierung?
Die Konvertierung von CSV zu SQL wandelt kommagetrennte Werte in Structured Query Language-Anweisungen um, die eine relationale Datenbank ausführen kann. Die häufigste Ausgabe ist ein Paar: eine CREATE TABLE-Anweisung, die Spalten definiert, und eine oder mehrere INSERT INTO-Anweisungen, die diese Spalten mit den Zeilen aus der CSV-Datei befüllen.
CSV-Dateien folgen der RFC 4180-Spezifikation. Jede Zeile ist ein Datensatz, Felder werden durch ein Trennzeichen (meist ein Komma) getrennt, und Felder, die das Trennzeichen oder Zeilenumbrüche enthalten, werden in doppelte Anführungszeichen eingeschlossen. SQL ist die Standardsprache zur Datenverwaltung in Systemen wie PostgreSQL, MySQL, SQLite und SQL Server. Die Konvertierung zwischen diesen beiden Formaten ist eine der häufigsten Datenimport-Aufgaben in der Softwareentwicklung.
Ein korrekter CSV-zu-SQL-Konverter behandelt Anführungszeichen korrekt, maskiert einfache Anführungszeichen in Werten (durch Verdopplung zu '' gemäß SQL-Standard), ordnet Spaltenüberschriften gültigen SQL-Bezeichnern zu und kann optional Datentypen ableiten. Über die grundlegende Maskierung hinaus normalisiert ein guter Konverter Spaltennamen (ersetzt Leerzeichen und Bindestriche durch Unterstriche) und schließt die Ausgabe in einen Transaktionsblock ein, sodass ein fehlgeschlagener Import sauber zurückgerollt wird statt unvollständige Daten in der Tabelle zu hinterlassen. Ohne einen Konverter ist das manuelle Schreiben von INSERT-Anweisungen selbst für wenige hundert Zeilen fehleranfällig und zeitaufwändig.
Warum einen CSV-zu-SQL-Konverter verwenden?
SQL INSERT-Anweisungen manuell aus Tabellendaten zu schreiben ist mühsam und fehleranfällig. Ein Konverter automatisiert die wiederkehrenden Aufgaben, sodass Sie sich auf Schema-Design und Datenvalidierung konzentrieren können.
Anwendungsfälle für CSV zu SQL
SQL-Datentypübersicht
Bei der Konvertierung von CSV zu SQL wird jede Spalte standardmäßig als TEXT definiert, da CSV keine Typmetadaten enthält. Wenn Sie die Spaltentypen kennen, können Sie TEXT in der CREATE TABLE-Ausgabe ersetzen. Diese Tabelle zeigt die gängigsten SQL-Typen und wann jeder verwendet wird.
| Typ | Verwendet für | Hinweise |
|---|---|---|
| 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 |
SQL-Dialekt-Vergleich
SQL-Syntax variiert zwischen Datenbank-Engines. Die generierten INSERT-Anweisungen verwenden Standard-SQL, das in den meisten Systemen funktioniert, aber bestimmte Funktionen unterscheiden sich. Diese Tabelle fasst die Unterschiede zusammen, die beim CSV-Import am wichtigsten sind.
| Funktion | 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: Eine Import-Methode wählen
Für kleine bis mittlere Datensätze (unter 10.000 Zeilen) funktionieren INSERT-Anweisungen gut und sind über alle SQL-Datenbanken portabel. Für große Importe bieten Datenbanken Bulk-Loading-Befehle, die den SQL-Parser vollständig umgehen.
Codebeispiele
Diese Beispiele zeigen, wie CSV in SQL INSERT-Anweisungen in verschiedenen Programmiersprachen umgewandelt werden kann. Jedes Beispiel behandelt die Maskierung einfacher Anführungszeichen und die Bereinigung von Spaltennamen.
// 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;"