Datenqualität // Grundlagen der Typ-Konvertierung mit T-SQL — CAST, CONVERT, TRY_CAST und TRY_CONVERT im Vergleich

Ein Datum aus einer CSV-Datei landet als Text in der Datenbank — und plötzlich wird aus dem 2. November der 11. Februar. Solche stillen Fehlinterpretationen sind der Klassiker bei der Typ-Konvertierung in SQL Server. Wer CASTCONVERTTRY_CAST und TRY_CONVERT samt Style-Parameter kennt, vermeidet sie.

Das Wichtigste vorab:

  • CAST ist ANSI-SQL-Standard und portabel; CONVERT (und TRY_CONVERT) sind SQL-Server-spezifisch.
  • TRY_CAST und TRY_CONVERT werfen keine Exception, sondern liefern im Fehlerfall NULL — ideal für ETL.
  • Der Style-Parameter (nur bei CONVERT / TRY_CONVERT) entscheidet, wie ein Text-Datum interpretiert wird.
  • Im ETL gilt: Eingangsformate (Datum, Zahl, Ja/Nein, NULL) vorab festlegen.

Voraussetzung: SQL Server mit SSMS; die Beispiele sind reines T-SQL ohne Sample-Datenbank.

Dieser Artikel gehört zur Serie Datenqualität in einem ETL-Prozess, in der ein Design Pattern vorgestellt wird, das die extrahierten Daten prüft, behandelt und schlechte Daten von der weiteren Verarbeitung ausschließt.

Welche Funktion wann? Die folgende Merkhilfe ordnet die vier Funktionen nach Einsatzzweck — die Abschnitte danach leiten die Details her:

AufgabeFunktion
Standard-Konvertierung, portabelCAST
Format explizit über Style steuernCONVERT
Fehlertolerant (NULL statt Exception)TRY_CAST
Fehlertolerant und Style-gesteuertTRY_CONVERT

CAST, CONVERT, TRY_CAST und TRY_CONVERT — der Überblick

SQL Server bietet mit CASTCONVERTTRY_CAST und TRY_CONVERT vier Funktionen zur Typ-Konvertierung. Die Syntax von CAST und TRY_CAST bzw. CONVERT und TRY_CONVERT ist jeweils identisch — der einzige Unterschied: TRY_CAST und TRY_CONVERT werfen bei einem nicht konvertierbaren Wert keine Exception, sondern liefern im Fehlerfall NULL.

Der Unterschied in einem Satz: CAST ist die ANSI-SQL-Standard-Funktion und läuft portabel auf praktisch jedem Datenbanksystem; CONVERT ist SQL-Server-spezifisch und bietet dafür den Style-Parameter, der explizit steuert, wie ein Text — besonders ein Datum — interpretiert wird. Die beiden folgenden Abschnitte leiten diese zwei Unterschiede im Detail her.

Unterschied 1: ANSI-SQL vs. SQL-Server-spezifisch

Zum einen ist CONVERT (und damit auch TRY_CONVERT) SQL-Server-spezifisch und entspricht nicht dem ANSI-SQL-Standard. Anders ausgedrückt: CAST gehört zum ANSI-SQL-Standard und ist deshalb in praktisch allen relationalen Datenbanksystemen verfügbar (OraclePostgres und anderen) — welche Konvertierungen im Einzelnen zulässig sind, unterscheidet sich jedoch je nach Hersteller. Ein CONVERT mit äquivalenter Funktionsweise gibt es dort meist nicht; auch TRY_CAST gehört nicht zum ANSI-SQL-Standard — SQL Server hat es eingeführt, einige andere Systeme bieten inzwischen aber ebenfalls eine TRY_CAST-Variante.

Unterschied 2: der Style-Parameter

Zum anderen besitzen CONVERT und TRY_CONVERT — anders als CAST und TRY_CAST — einen Style-Parameter, mit dem sich steuern lässt, wie SQL Server den übergebenen Wert interpretiert. Ein Beispiel hierfür ist ein Datum, das als Text an die Funktionen CAST oder CONVERT übergeben wird. Für das Datum gibt es in den Ländern dieser Welt sehr unterschiedliche Schreibweisen. Das Datum 02.11.2024 (deutsche Schreibweise) wird gemäß der folgenden Tabelle sehr unterschiedlich notiert:

LandFormatstringDatumStyle-Parameter
Deutschlanddd.mm.yyyy02.11.2024104
USAmm-dd-yyyy11-02-2024110
Japanyyyy/mm/dd2024/11/02111

Eine zuverlässige Konvertierung kann nur dann erfolgen, wenn wir das Datumsformat und den korrekten Style-Parameter kennen. Die folgenden SELECT Statements verdeutlichen die Problematik:

  1: SELECT CAST('02.11.2024' AS date);       -- 2024-02-11
  2: SELECT CAST('11-02-2024' AS date);       -- 2024-11-02
  3: SELECT CAST('2024/11/02' AS date);       -- 2024-11-02
  4: 
  5: SELECT CONVERT(date, '02.11.2024', 104); -- 2024-11-02
  6: SELECT CONVERT(date, '2024/11/02', 111); -- 2024-11-02
  7: SELECT CONVERT(date, '11-02-2024', 110); -- 2024-11-02
  8: 
  9: SELECT CONVERT(date, '02.11.2024', 111);
 10:  -- Exception: Conversion failed when converting date and/or
 11:  --              time from character string.

Die hinter den Kommentarzeichen notierten Werte stammen aus dem Resultset im SQL Server Management Studio; SSMS stellt einen date-Wert standardmäßig im ISO-Format yyyy-MM-dd dar. Wichtig: Wie CAST einen textuellen Datums-String interpretiert, hängt von der LANGUAGE– bzw. DATEFORMAT-Einstellung der Session ab — die hier gezeigten Ergebnisse gelten für die Default-Session (us_english, also mdy). Unter dieser Einstellung interpretiert CAST das deutsche Datum in Zeile 1 falsch: statt 02.11.2024 erhalten wir 11.02.2024 (unter dmy käme das korrekte 02.11.2024 heraus, bei anderen Werten auch ein Konvertierungsfehler). Genau deshalb sollte man sich bei textuellen Datumsangaben nie auf die implizite Interpretation verlassen — mit dem korrekten Style-Parameter 104 in Zeile 5 liest CONVERT ein deutsches Datum dagegen zuverlässig.

Was das für ETL bedeutet

Ohne an dieser Stelle genauer auf die Probleme bei der Typ-Konvertierung in Abhängigkeit von dem Datentyp einzugehen, sollten zwei Dinge klar sein:

  • Eine sichere Typ-Konvertierung kann eine herausfordernde Angelegenheit sein. Das gilt übrigens auch für vermeintlich einfache Datentypen wie decimal und float.
  • Bei der Entwicklung eines ETL-Prozesses, bei dem die zu verarbeitenden Daten aus Dateien extrahiert werden (CSV, XML, JSON, …), ist es unerlässlich, genau festzulegen, in welchem Format ein Datum, eine Zahl, eine Ja/Nein-Information, ein NULL und anderes geliefert werden.

Die Folge-Serie Datenqualität // Sichere Typ-Konvertierung mit T-SQL verwendet (fast) ausschließlich die Funktion TRY_CONVERT für die Typ-Konvertierung. Grund hierfür ist die Möglichkeit der Angabe eines Style-Parameters, über den sich die Interpretation des Eingangswertes steuern lässt.

Sofern die hier vorgestellte Systematik der Typ-Konvertierung auf ein anderes Datenbank-System zu portieren ist, sind äquivalente Funktionen zu finden oder gegebenenfalls selbst zu programmieren. Mir ist bewusst, dass die Verwendung einer nicht-ANSI-SQL-Funktion die Portabilität hemmt. Bei Verwendung der Funktion CAST würde zusätzlicher Entwicklungsaufwand entstehen und gegebenenfalls die Les- und Wartbarkeit der erforderlichen T-SQL-Artefakte beeinträchtigen.

In Postgres: CAST ja, TRY_CONVERT nein

Wer dieselbe Logik in Postgres braucht, findet einen Teil davon wieder — aber nicht alles. CAST (bzw. die Kurzform wert::typ) ist auch in Postgres ANSI-Standard und besitzt dieselbe Syntax — welche Konvertierungen im Einzelnen zulässig sind, kann sich je nach System aber unterscheiden. Einen direkten Ersatz für CONVERT mit Style-Parameter oder für TRY_CONVERT / TRY_CAST gibt es jedoch nicht:

  • Datums- und Zahlenformate steuerst du über to_date(text, format) bzw. to_number(text, format) mit expliziter Formatmaske — z. B. to_date('02.11.2024', 'DD.MM.YYYY').
  • Eine fehlertolerante Konvertierung (NULL statt Exception) ist nicht eingebaut. Üblich ist eine kleine PL/pgSQL-Hilfsfunktion mit BEGIN … EXCEPTION WHEN others THEN RETURN NULL; END; oder eine Vorab-Prüfung des Eingangswerts.

Die Grundregel bleibt dieselbe — Eingangsformat kennen, Konvertierung absichern — nur das Werkzeug heißt anders.

FAQ

CAST oder CONVERT — was soll ich nehmen?

CAST ist ANSI-SQL und portabel — die erste Wahl, wenn keine Format-Steuerung nötig ist. CONVERT brauchst du immer dann, wenn du über den Style-Parameter steuern musst, wie ein Text (besonders ein Datum) interpretiert wird. Im ETL-Kontext führt deshalb meist kein Weg an CONVERT bzw. TRY_CONVERT vorbei.

Warum gibt TRY_CONVERT ein NULL statt einer Fehlermeldung zurück?

Genau das ist der Zweck: TRY_CONVERT und TRY_CAST brechen die Verarbeitung nicht mit einer Exception ab, sondern liefern bei nicht konvertierbaren Werten NULL. So lassen sich in einem ETL-Lauf schlechte Datensätze erkennen und gezielt aussteuern, statt dass der ganze Batch abbricht.

Wofür ist der Style-Parameter?

Der Style-Parameter (drittes Argument von CONVERT / TRY_CONVERT) legt fest, nach welchem Schema ein Text interpretiert wird — etwa 104 für das deutsche Datumsformat dd.mm.yyyy. Ohne passenden Style interpretiert SQL Server ein Text-Datum abhängig von der LANGUAGE– bzw. DATEFORMAT-Einstellung der Session — und liefert leicht ein falsches Ergebnis (siehe Zeile 1 im Beispiel oben).

Funktioniert das auch in Postgres?

Teilweise — siehe Abschnitt „In Postgres“CAST ja, CONVERT / TRY_CONVERT nein; die Format-Steuerung läuft dort über to_date / to_number, eine fehlertolerante Konvertierung über eine eigene Hilfsfunktion.

Verwandte Artikel