CSV-zu-SQLkonverter

Anleitung für Entwickler · 9 Min. Lesezeit

CSV in SQL mit Python umwandeln: Code-Beispiel und wann ein Tool reicht

CSV in SQL mit Python umwandeln: komplettes Code-Beispiel mit dem csv-Modul, sicheres Parametrisieren statt String-Bau, CREATE TABLE plus INSERT, und die ehrliche Antwort, wann ein Skript sinnvoller ist als ein fertiges Tool.

Jan-Tristan Rudat
Jan-Tristan Rudat Veröffentlicht Geprüft

Kurz gesagt

Um eine CSV in SQL mit Python umzuwandeln, lesen Sie die Datei mit dem Standardmodul csv, bestimmen Spaltennamen und Datentypen, bauen ein CREATE TABLE und fügen die Zeilen mit parametrisierten Platzhaltern (nicht per String-Bau) ein. Dieser Artikel zeigt ein vollständiges, lauffähiges Skript und nennt ehrlich, wann ein fertiges Tool wie unser Konverter die bessere Wahl ist: bei einmaligen Importen, sensiblen Daten oder fehlender Python-Umgebung.

Python oder Tool: die ehrliche Vorab-Frage

Eine CSV in SQL umzuwandeln klingt nach einem winzigen Skript, und das ist es im Kern auch. Trotzdem lohnt es sich, kurz innezuhalten, bevor Sie eine Datei convert.py anlegen. Denn ein eigenes Python-CSV-to-SQL-Skript ist immer dann die richtige Wahl, wenn der Vorgang wiederholbar und automatisierbar sein soll: ein nächtlicher Cronjob, ein Import als Teil einer Pipeline, eine Datei, die jede Woche im selben Format eintrifft. Hier zahlt sich Code aus, weil er ohne Mausklicks läuft und sich versionieren lässt.

Geht es dagegen um einen einmaligen Import, um eine Datei, die Sie schnell in eine Datenbank bekommen wollen, ist ein Skript oft Overhead. Sie müssten Python installiert haben, das richtige Encoding treffen, das Trennzeichen kennen und die Typ-Erkennung selbst schreiben. Für genau diese Fälle gibt es unseren CSV-zu-SQL-Konverter, der dasselbe Ergebnis, also CREATE TABLE plus INSERT, ohne jede Installation und vollständig im Browser liefert. Wie der Weg über das Tool aussieht, beschreibt der Ratgeber CSV in SQL umwandeln Schritt für Schritt.

Dieser Artikel zeigt beides: ein kompaktes, abhängigkeitsfreies Skript, das Sie kopieren und anpassen können, und am Ende eine ehrliche Entscheidungshilfe, wann das Skript und wann das Tool die schnellere Lösung ist.

Vorbereitung: was du brauchst

Das Schöne an Python ist, dass für den Standardfall keine externe Bibliothek nötig ist. Sowohl das CSV-Lesen als auch eine einfache Datenbank sind in der Standardbibliothek enthalten:

  • Python 3: Version 3.8 oder neuer genügt. Es sind keine zusätzlichen Pakete erforderlich.
  • Das Modul csv: liest die Datei zeilenweise, respektiert Anführungszeichen und eingebettete Trennzeichen nach RFC 4180.
  • Das Modul sqlite3: bringt eine vollwertige, dateibasierte Datenbank mit, ideal zum Testen. Für MySQL oder PostgreSQL tauschen Sie nur den Treiber aus.

Als Beispiel nehmen wir eine kleine Datei kunden.csv mit einem deutschen Klassiker, dem Semikolon als Trennzeichen, weil deutsches Excel so exportiert:

id;name;stadt;umsatz
1;Anna Berg;Hamburg;1240.50
2;Tom O'Neil;Köln;980.00
3;Lea Voß;Bremen;1510.20

Warum Excel im deutschen Raum überhaupt das Semikolon nutzt und wie Sie damit umgehen, erklärt ausführlich der Ratgeber CSV mit Semikolon in SQL.

CSV mit dem csv-Modul lesen

Der erste Schritt ist immer das saubere Einlesen. Drei Details entscheiden hier über Erfolg oder kaputte Daten, und sie werden gern übersehen. Erstens das Encoding: Deutsche Exporte sind oft utf-8, manchmal aber auch cp1252 oder latin-1. Geben Sie es explizit an, sonst landen Umlaute als Buchstabensalat in der Datenbank. Zweitens das Argument newline="" beim Öffnen, das verhindert, dass das csv-Modul Zeilenumbrüche doppelt interpretiert. Drittens das Trennzeichen, das Sie mit delimiter setzen oder über csv.Sniffer automatisch erkennen lassen.

Mit csv.DictReader erhalten Sie jede Zeile als Dictionary, dessen Schlüssel die Spaltennamen aus der Kopfzeile sind. Das macht den Code lesbar, weil Sie Spalten über ihren Namen ansprechen statt über Indizes.

Das vollständige Code-Beispiel

Hier ist ein lauffähiges CSV-SQL-Skript, das eine CSV liest, je Spalte einen Datentyp errät, ein CREATE TABLE erzeugt und die Zeilen sicher und parametrisiert in eine SQLite-Datenbank schreibt. Es kommt ohne externe Pakete aus:

import csv
import sqlite3
import re

CSV_PFAD = "kunden.csv"
DB_PFAD = "kunden.db"
TABELLE = "kunden"
TRENNZEICHEN = ";"  # deutsches Excel: oft Semikolon


def ident(name: str, fallback: str) -> str:
    """Spaltenname zu gueltigem SQL-Identifier."""
    t = re.sub(r"[^A-Za-z0-9_]", "_", (name or "").strip())
    if not t:
        t = fallback
    if t[0].isdigit():
        t = "_" + t
    return t.lower()


def erkenne_typ(werte: list[str]) -> str:
    """Engsten passenden Typ ueber alle nicht-leeren Werte ermitteln."""
    nicht_leer = [w.strip() for w in werte if w and w.strip()]
    if not nicht_leer:
        return "TEXT"
    if all(re.fullmatch(r"-?\d+", w) and not re.match(r"-?0\d", w) for w in nicht_leer):
        return "INTEGER"
    if all(re.fullmatch(r"-?\d+(?:[.,]\d+)?", w) for w in nicht_leer):
        return "REAL"
    return "TEXT"


def csv_in_sql(csv_pfad: str, db_pfad: str, tabelle: str, trennzeichen: str) -> None:
    # Schritt 1: CSV einlesen (Encoding und newline beachten)
    with open(csv_pfad, newline="", encoding="utf-8") as f:
        leser = csv.DictReader(f, delimiter=trennzeichen)
        spalten = [ident(c, f"col{i+1}") for i, c in enumerate(leser.fieldnames)]
        roh_spalten = leser.fieldnames
        zeilen = list(leser)

    if not zeilen:
        print("Keine Datenzeilen gefunden.")
        return

    # Schritt 2: Typ je Spalte erkennen
    typen = [
        erkenne_typ([z[rs] for z in zeilen])
        for rs in roh_spalten
    ]

    # Schritt 3: CREATE TABLE bauen
    spalten_def = ",\n  ".join(
        f'"{sp}" {tp}' for sp, tp in zip(spalten, typen)
    )
    create_sql = f'CREATE TABLE IF NOT EXISTS "{tabelle}" (\n  {spalten_def}\n);'

    # Schritt 4: Werte parametrisiert einfuegen (NIE per String-Bau)
    platzhalter = ", ".join("?" for _ in spalten)
    spaltenliste = ", ".join(f'"{sp}"' for sp in spalten)
    insert_sql = f'INSERT INTO "{tabelle}" ({spaltenliste}) VALUES ({platzhalter})'

    daten = [
        tuple(z[rs] if z[rs] != "" else None for rs in roh_spalten)
        for z in zeilen
    ]

    verbindung = sqlite3.connect(db_pfad)
    try:
        verbindung.execute(create_sql)
        verbindung.executemany(insert_sql, daten)  # sicheres Escaping durch den Treiber
        verbindung.commit()
        print(f"{len(daten)} Zeilen in '{tabelle}' importiert.")
    finally:
        verbindung.close()


if __name__ == "__main__":
    csv_in_sql(CSV_PFAD, DB_PFAD, TABELLE, TRENNZEICHEN)

Das Skript erledigt vier Aufgaben, die jeder Konverter ähnlich lösen muss: Es liest die CSV ein, normalisiert die Spaltennamen zu gültigen Bezeichnern, errät je Spalte einen Typ und schreibt die Daten in die Tabelle. Die Typ-Erkennung ist bewusst einfach gehalten (Ganzzahl, Kommazahl, sonst Text). Wie eine robustere Erkennung funktioniert und welche Fallen lauern, etwa Postleitzahlen mit führender Null, erklärt der Ratgeber Datentypen aus CSV richtig erkennen.

Möchten Sie statt eines direkten Datenbank-Imports lieber eine fertige .sql-Datei mit ausführbaren INSERT-Statements erzeugen, ändern Sie nur den letzten Schritt: Statt executemany schreiben Sie die Statements als Text in eine Datei. Worauf es bei den reinen Anweisungen ankommt, vertieft der Ratgeber INSERT-Statements aus CSV erzeugen.

Warum parametrisieren statt String-Bau

Der wichtigste Punkt im ganzen Skript ist unscheinbar: die Fragezeichen als Platzhalter und executemany. Viele Anleitungen im Netz bauen die Werte direkt in den SQL-String, etwa per f-String. Das ist aus zwei Gründen gefährlich.

Erstens zerbrechen Strings. Sobald ein Wert ein Apostroph enthält, wie in Tom O'Neil, beendet das einfache Anführungszeichen das SQL-Literal vorzeitig und das Statement wird ungültig. Zweitens, und deutlich ernster: Ungeprüft eingefügte Werte sind die klassische Eintrittstür für SQL-Injection. Eine CSV ist keine vertrauenswürdige Quelle, sie kann aus einem fremden Export oder Upload stammen.

Parametrisierte Anweisungen lösen beides. Sie übergeben dem Treiber den SQL-Rahmen mit Platzhaltern und die Werte separat als Tupel. Der Datenbanktreiber kümmert sich um das korrekte und sichere Einsetzen, ganz ohne dass Sie selbst Apostrophe verdoppeln müssen. Wenn Sie dagegen INSERT-Statements als reinen Text generieren, etwa um sie weiterzugeben, dann müssen Sie das Escaping selbst übernehmen, also jeden Apostroph durch zwei ersetzen. Warum genau das so kritisch ist und wie es portabel für alle Dialekte funktioniert, beschreibt der Ratgeber Sonderzeichen, Apostrophe und SQL-Injection.

Für MySQL oder PostgreSQL bleibt die Struktur des Skripts gleich, Sie tauschen nur Treiber und Platzhalter-Syntax aus. Mit mysql-connector-python oder psycopg2 nutzen Sie statt des Fragezeichens den Platzhalter %s. Das ist auch der Punkt, an dem Sie sich für einen CSV-Import in MySQL entscheiden, wo neben dem Skript auch LOAD DATA INFILE als sehr schneller Weg zur Verfügung steht.

Die Pandas-Variante mit to_sql

Wer ohnehin mit Pandas arbeitet oder die Daten vor dem Import auswerten will, kommt mit deutlich weniger Code aus. read_csv liest die Datei und errät die Typen, to_sql legt die Tabelle an und schreibt alle Zeilen in einem Rutsch:

import pandas as pd
from sqlalchemy import create_engine

df = pd.read_csv("kunden.csv", sep=";", dtype={"id": "Int64"})
# fuehrende Nullen schuetzen: betroffene Spalten als Text laden
# df = pd.read_csv("kunden.csv", sep=";", dtype={"plz": str})

engine = create_engine("sqlite:///kunden.db")
df.to_sql("kunden", engine, if_exists="replace", index=False)
print(f"{len(df)} Zeilen importiert.")

Das ist bequem, hat aber einen Preis: Pandas und SQLAlchemy sind große Abhängigkeiten, die Sie installieren und mitschleppen müssen. Für ein schlankes Hilfsskript ist die Standardbibliothek meist die elegantere Lösung. Pandas spielt seine Stärke aus, wenn Sie die Daten vor dem Import filtern, transformieren oder zusammenführen, dann ist to_sql nur der letzte Schritt einer längeren Verarbeitung. Achten Sie auch hier auf führende Nullen: ohne dtype=str macht Pandas aus einer Postleitzahl wie 04109 die Zahl 4109.

Wann ein Tool die bessere Wahl ist

Jetzt die versprochene ehrliche Einordnung. Ein Python-Skript ist mächtig, aber nicht für jede Situation die schnellste oder sinnvollste Lösung. Die folgende Tabelle hilft bei der Entscheidung:

Situation Empfehlung
Einmaliger Import, schnell erledigt Tool
Wiederkehrend, automatisiert, im Cronjob Python-Skript
Keine Python-Umgebung vorhanden Tool
Daten müssen vorher gefiltert oder umgebaut werden Python (Pandas)
Sensible Daten, die das Gerät nicht verlassen sollen Beides, Tool läuft lokal im Browser
Nur schnell sauberes CREATE TABLE plus INSERT als Text Tool

Ein häufiges Missverständnis lautet: Online-Konverter sind unsicher, also schreibe ich lieber selbst Code. Das stimmt für Tools, die Ihre Datei auf einen fremden Server laden. Unser Konverter tut das gerade nicht. Das Parsen der CSV und das Erzeugen der SQL-Statements laufen zu 100 Prozent lokal in Ihrem Browser, es gibt keinen Upload, kein Konto und kein Limit. Die Datei verlässt Ihr Gerät genauso wenig wie bei einem lokalen Python-Skript. Damit fällt das stärkste Argument gegen ein Tool bei sensiblen Daten weg, ein Detail, das die meisten englischsprachigen Konverter offen lassen.

Unterm Strich gilt: Für alles, was wiederholbar, programmierbar oder Teil einer größeren Verarbeitung ist, lohnt sich das Skript aus diesem Artikel. Für den schnellen, einmaligen Weg von der Tabelle zum fertigen SQL ist das Tool unschlagbar bequem. Probieren Sie es direkt aus mit dem CSV-zu-SQL-Konverter, oder stöbern Sie durch alle Ratgeber im Überblick.

Häufige Fragen

Wie wandle ich eine CSV-Datei mit Python in SQL um?

Sie lesen die CSV mit dem Standardmodul csv ein, bestimmen Spaltennamen und Datentypen, bauen ein CREATE TABLE und fügen die Zeilen mit parametrisierten Platzhaltern über executemany ein. Für SQLite reicht das mitgelieferte Modul sqlite3 ohne weitere Installation.

Brauche ich Pandas, um CSV nach SQL zu bringen?

Nein. Mit DataFrame.to_sql ist Pandas sehr bequem für einmalige Importe in eine bestehende Datenbank. Für ein schlankes, abhängigkeitsfreies Skript genügen aber die Standardmodule csv und sqlite3. Pandas lohnt sich vor allem, wenn Sie die Daten ohnehin auswerten oder transformieren.

Warum soll ich die Werte nicht selbst in den SQL-String schreiben?

Weil das fehleranfällig und unsicher ist. Apostrophe und Sonderzeichen können das Statement zerstören, und ungeprüft eingefügte Werte öffnen die Tür für SQL-Injection. Nutzen Sie stattdessen parametrisierte Anweisungen mit Platzhaltern, dann übernimmt der Datenbanktreiber das Escaping sicher.

Wann reicht ein fertiges Tool statt eines Python-Skripts?

Wenn es ein einmaliger Import ist, wenn keine Python-Umgebung vorhanden ist, wenn die Daten sensibel sind und das Gerät nicht verlassen sollen, oder wenn Sie schnell sauberes CREATE TABLE plus INSERT als Text brauchen. Dann ist ein client-side Konverter wie csv-sql.de schneller und ohne Installation nutzbar.

Wie gehe ich mit führenden Nullen bei Postleitzahlen um?

Behandeln Sie solche Spalten bewusst als Text. Eine automatische Typ-Erkennung macht aus 04109 sonst die Zahl 4109 und verliert die führende Null. In Python zwingen Sie die Spalte auf TEXT, im Tool setzen Sie den Spaltentyp manuell auf Text.

Weiterführende Artikel

Anzeige
Anzeige
Anzeige
Anzeige
Anzeige