Wer einmal einen Kassen-Report mit Werten wie '1.234,56 €' aus einer CSV in eine SQL-Server-Datenbank importieren musste, kennt das Muster: TRY_CONVERT(money, '1,234.56') liefert 1234.5600. Doch TRY_CONVERT(money, '1.234,56') liefert NULL. Und selbst wenn der Import sauber läuft: money / 100 * 100 ist nicht zwangsläufig dasselbe wie der Ausgangswert.
Auf einen Blick:
money(±922 337 203 685 477, 8 Byte) undsmallmoney(±214 748,3647, 4 Byte) speichern fest vier Nachkommastellen — ihr Wertebereich lässt sich vollständig mitdecimal(19, 4)beziehungsweisedecimal(10, 4)abbilden.- Der Rundungs-Pitfall:
money / 100 * 100ist nicht zwangsläufig der Ausgangswert, denn jedes Zwischen-Ergebnis rundet implizit auf vier Nachkommastellen. Für mehrstufige Arithmetik istdecimal(p, s)die bessere Wahl. - Bei Text-Eingaben ignoriert
TRY_CONVERTdas Komma (aus'123,45'wird12345.00), und die leere Zeichenfolge wird zu0.00. Das sichere Pattern behandelt beide Fälle. - In Postgres ist
numeric(19, 4)das portable Pendant — der Postgres-eigenemoney-Typ hängt am Session-Localelc_monetary. Ein direktes Try-Pendant fehlt, der Artikel zeigt den PL/pgSQL-Wrapperfn_try_cast_numeric_19_4.
Voraussetzung: TRY_CONVERT gibt es seit SQL Server 2012. Das sichere Pattern verwendet zusätzlich TRIM und braucht damit SQL Server 2017+ (davor LTRIM(RTRIM(…))). Alle Beispiele arbeiten mit Inline-Literalen ohne Sample-Datenbank. Die Postgres-Seite setzt keine bestimmte Version voraus, nur der pg_input_is_valid-Hinweis braucht Postgres 16 oder neuer.
Inhalt
- Wertebereich und Speicherbedarf
- Rundungs-Pitfall — money vs. decimal
- Text nach money konvertieren
- Typisierte Zahlen nach money konvertieren
- Sichere Typ-Konvertierung
- Postgres-Brücke
- Zusammenfassung
- FAQ
- Verwandte Artikel
Wertebereich und Speicherbedarf
SQL Server stellt für die Speicherung von Währungswerten zwei Datentypen zur Verfügung. Beide haben fest vier Nachkommastellen. Ihr Wertebereich lässt sich vollständig mit einem decimal(p, 4) passender Gesamt-Stellenzahl abbilden. Trotzdem sind money und decimal nicht dasselbe: Speicherung und Verhalten in Berechnungen unterscheiden sich (siehe Rundungs-Pitfall).
| Typ | Min | Max | Bytes | Nachkommastellen | decimal-Abbildung |
|---|---|---|---|---|---|
money | −922 337 203 685 477,5808 | +922 337 203 685 477,5807 | 8 | 4 | decimal(19, 4) |
smallmoney | −214 748,3648 | +214 748,3647 | 4 | 4 | decimal(10, 4) |
Praktische Konsequenz für die Typ-Wahl: smallmoney ist nur dort sinnvoll, wo der Wertebereich sicher unter ±214 748 bleibt (Speicher-Halbierung, 4 statt 8 Byte). Wird der smallmoney-Wertebereich nicht garantiert eingehalten, ist money die größere der beiden Währungsvarianten. Für neue Modelle, deren Werte in Berechnungen einfließen, lohnt vorab die Prüfung, ob nicht ohnehin decimal(p, s) passt (nächster Abschnitt).
Rundungs-Pitfall — money vs. decimal
Die Datentypen money und smallmoney weisen eine Besonderheit bei mehrstufigen Berechnungen auf: Bei money / 100 bleibt der Ergebnistyp money (gegenüber int hat money die höhere Typ-Präzedenz), und damit steht dem Zwischen-Ergebnis nur die feste Skala von vier Nachkommastellen zur Verfügung. Der Rundungsverlust eines Teilschritts geht so in den nächsten ein. Bei decimal(p, s) bestimmt SQL Server Precision und Skala des Ergebnisses nach eigenen Regeln — in der Division wächst zunächst die Skala. Erst die Precision-Obergrenze 38 kann auch dort Rundung erzwingen (siehe unten).
1: SELECT CAST(123.45678 AS money) AS [Output]; -- 123.4568
2: SELECT CAST(123.45678 AS money) / 100 AS [Output]; -- 1.2345 (Verlust ab hier)
3: SELECT CAST(123.45678 AS money) / 100 * 100 AS [Output]; -- 123.4500 (nicht gleich 123.4568)
1: SELECT CAST(123.45678 AS decimal(10, 4)) AS [Output]; -- 123.4568
2: SELECT CAST(123.45678 AS decimal(10, 4)) / 100 AS [Output]; -- 1.23456800
3: SELECT CAST(123.45678 AS decimal(10, 4)) / 100 * 100 AS [Output]; -- 123.45680000
Bei der Verwendung des Datentyps money verliert das Ergebnis in der ersten Division an Genauigkeit. Der Wert aus Zeile 3 ist nicht mehr identisch mit dem Ausgangswert aus Zeile 1. Bei decimal(10, 4) liefert dieselbe Berechnung den Ausgangswert vollständig zurück — in diesem Beispiel. Bei komplexeren Ausdrücken können die Precision-/Scale-Regeln von SQL Server (Obergrenze 38) auch bei decimal zu Rundung führen.
Kernaussage: Bei mehrstufigen Reporting-Berechnungen (Brutto/Netto, Steuer-Aufrechnungen, Allokations-Schlüssel) akkumuliert die implizite money-Zwischen-Rundung Fehler. Wer money nur für die Speicher-Spalten verwendet und für die Arithmetik auf decimal(p, s) ausweicht, vermeidet das — siehe auch Datenqualität in SQL Server // TRY_CONVERT für decimal und numeric sicher anwenden.
Text nach money konvertieren
Text-Eingangswerte kommen typischerweise aus CSV-Importen mit Betrags-Spalten. Wird ein solcher nvarchar-/varchar-Wert an TRY_CONVERT übergeben, erwartet die Konvertierung den Punkt als einziges Dezimaltrennzeichen. Ein Komma im Text wird nicht als Dezimaltrennzeichen interpretiert, sondern wie ein Gruppierungszeichen ignoriert, und mehr als vier Nachkommastellen rundet die Konvertierung auf die vierte. Die leere Zeichenfolge wird zu 0.00 konvertiert. Das ist ein wichtiger Unterschied zum decimal-Ziel: TRY_CONVERT(decimal(19, 4), N'') liefert NULL.
1: SELECT TRY_CONVERT(money, NULL ) -- NULL
2: SELECT TRY_CONVERT(money, N'12345678' ) -- 12345678.00
3: SELECT TRY_CONVERT(money, N'123,45678' ) -- 12345678.00
4: SELECT TRY_CONVERT(money, N'123.45678' ) -- 123.4568
5: SELECT TRY_CONVERT(money, N'' ) -- 0.00
6: SELECT TRY_CONVERT(money, N' ' ) -- 0.00
7: SELECT TRY_CONVERT(money, N' 123.45678') -- 123.4568
8: SELECT TRY_CONVERT(money, N'123.45678 ') -- 123.4568
9: SELECT TRY_CONVERT(money, N'12345678E-3') -- NULL
10: SELECT TRY_CONVERT(money, N'1,234.5678' ) -- 1234.5678
11: SELECT TRY_CONVERT(money, N'1.234.5678' ) -- NULL
12: SELECT TRY_CONVERT(money, N'1,2,3,4' ) -- 1234.00
13: SELECT TRY_CONVERT(money, N'1,2,3.4' ) -- 123.40
14: SELECT TRY_CONVERT(money, N'1,2.3.4' ) -- NULL
15: SELECT TRY_CONVERT(money, N'1,2.3,4' ) -- 12.34
Die Zeilen zeigen im Einzelnen:
- Zeile 2: Eine reine Ziffernfolge konvertiert wie erwartet.
- Zeile 3: Das Komma wird nicht als Dezimaltrennzeichen interpretiert, sondern ignoriert: Aus
'123,45678'wird12345678.00— ein fachlich falscher Wert, ganz ohne Fehlersignal. - Zeile 4: Der Punkt wirkt als Dezimaltrennzeichen, die fünfte Nachkommastelle wird auf die vierte gerundet.
- Zeilen 5, 6: Eine leere Zeichenfolge und ein String nur aus Leerzeichen werden zu
0.00konvertiert, nicht zuNULL. - Zeilen 7, 8: Führende und folgende Leerzeichen sind erlaubt und ändern das Ergebnis nicht.
- Zeile 9: Wissenschaftliche Notation wird als Text nicht akzeptiert. Als typisierte Zahl funktioniert sie (nächste Sektion). Wie das Pattern damit umgeht, steht in dessen Einschränkungen.
- Zeilen 10–15: Die Kombinations-Fälle zeigen beobachtetes Verhalten, keine dokumentierte Parser-Grammatik: In den getesteten Eingaben wirkt ein einzelner Punkt als Dezimaltrennzeichen, Kommas werden als Gruppierungszeichen ignoriert, ab dem zweiten Punkt liefert die Konvertierung
NULL. Als Validierung deutscher Zahlennotation taugt dieses Verhalten ausdrücklich nicht.
Kernaussage: Für ETL-Prozesse ist die kritischste Eigenheit dieser Konvertierung nicht das NULL, sondern der stille Falschwert: Das geschluckte Komma macht aus '123,45' ein 12345.00, ohne Fehler und ohne Warnung. Zusammen mit der leeren Zeichenfolge, die zu 0.00 wird, sind das die zwei Fälle, die das Pattern in „Sichere Typ-Konvertierung“ vorab behandelt.
Typisierte Zahlen nach money konvertieren
Kommt der Eingangswert bereits typisiert an (int, float, decimal), konvertiert TRY_CONVERT jeden numerischen Wert nach money, solange er in den Wertebereich passt. Werte mit mehr als vier Nachkommastellen werden auf die vierte gerundet — der Wert kann sich also schon bei der Konvertierung ändern.
1: SELECT TRY_CONVERT(money, NULL ) -- NULL
2: SELECT TRY_CONVERT(money, 12345678 ) -- 12345678.00
3: SELECT TRY_CONVERT(money, 123,45678 ) -- 123.00
4: SELECT TRY_CONVERT(money, 123.45678 ) -- 123.4568
5: SELECT TRY_CONVERT(money, 12345678E-5) -- 123.4568
Die Zeilen zeigen im Einzelnen:
- Zeile 3:
123,45678ist keine Dezimalzahl. Das Komma trennt hier Funktions-Argumente:TRY_CONVERTerhält die Ganzzahl123als Eingangswert und45678als style-Parameter, der fürmoneywirkungslos ist. - Zeile 4: Das Dezimal-Literal
123.45678(von T-SQL alsnumeric(8, 5)typisiert) wird auf die vierte Nachkommastelle gerundet. - Zeile 5:
12345678E-5ist einfloat-Literal (E-Notation erzeugtfloat) und wird ebenfalls zu123.4568gerundet. Als Text (Zeile 9 der vorigen Sektion) ergibt dieselbe NotationNULL.
Anders als bei den Integer-Zielen, die Nachkommastellen abschneiden (siehe Datenqualität in SQL Server // TRY_CONVERT für bigint, int, smallint und tinyint sicher anwenden), rundet die Konvertierung nach money. Für smallmoney greift zusätzlich der engere Wertebereich: Werte außerhalb ±214 748,3647 quittiert TRY_CONVERT mit NULL, wo CONVERT einen Laufzeitfehler auslöst.
Sichere Typ-Konvertierung
„Sicher“ meint in dieser Serie fehlertolerant: kein Abbruch, NULL statt Laufzeitfehler. Semantisch korrekt ist damit noch nichts garantiert — gerade bei money liefert eine „erfolgreiche“ Konvertierung mitunter einen falschen Wert, weil das ignorierte Komma aus '123,45' still 12345.00 macht. Das Pattern unten beseitigt genau die zwei beschriebenen stillen Fehlkonvertierungen. Es validiert nicht die vollständige Eingabegrammatik: Normalisieren ist kein Validieren.
Zwei Sonderfälle aus den Sektionen oben brauchen im Import-Pfad eine explizite Behandlung:
- Leere Zeichenfolge →
0.00: Wenn das fachlich falsch ist (der Regelfall bei CSV-Importen), muss die leere Zeichenfolge vor demTRY_CONVERTaufNULLgemappt werden. - Dezimal-Komma → ignoriert: Liefert die Quelle deutsche Notation, muss das Komma vor der Konvertierung durch einen Punkt ersetzt werden — sonst entsteht der stille Falschwert.
Das folgende Beispiel löst beide Sonderfälle direkt am money-Ziel, ohne Umweg über andere Typen. Es setzt voraus, dass die Quelle verlässlich deutsche Notation liefert — die Einschränkungen folgen unter dem Beispiel:
1: DECLARE @p_input AS nvarchar(30);
2: SET @p_input = N'123,45678';
3:
4: SELECT TRY_CONVERT( money
5: , REPLACE( CASE WHEN TRIM(@p_input) = ''
6: THEN NULL
7: ELSE @p_input
8: END
9: , ','
10: , '.'
11: )
12: ) AS [Output]; -- 123.4568
Zwei Einschränkungen gehören zu dem Pattern dazu:
- Eingabegrammatik: Das Pattern normalisiert ausschließlich das Dezimal-Komma und setzt damit ein bekanntes Quell-Locale voraus. Bei US-Notation würde dieselbe Ersetzung aus
'1,234'(gemeint:1234) ein1.234machen — die Normalisierung selbst erzeugt dann den stillen Falschwert (siehe Entscheidungsmatrix: unbekanntes Locale → zurückweisen). Tausenderpunkte ('1.234,56') und Währungszeichen wie das€aus dem Eingangs-Beispiel muss eine vorgelagerte Bereinigung entfernen, sonst stehen nach der Komma-Ersetzung zwei Punkte im String und das Ergebnis istNULL. UndTRIMentfernt ohne weitere Angabe nur das normale Leerzeichen (char(32)), einen String aus Tabs oder anderem Unicode-Leerraum erkennt das Pattern deshalb nicht als „leer“. - E-Notation bewusst außen vor: Als Text ergibt sie weiterhin
NULL(Zeile 9 der Test-Matrix). Gehört sie ausdrücklich zum Eingangsschema, ist sie ein separater Fall: Einfloat-Zwischenschritt (TRY_CONVERT(float, …)vor demmoney-Ziel) parst sie, arbeitet aber mit 15–17 signifikanten Stellen, währendmoneybis zu 19 trägt (15 Vorkommastellen plus 4 Nachkommastellen). Für Geldbeträge ist das eine Parsing-Notlösung mit Präzisionsrisiko und kein Default — sonst ist E-Notation besser ein Datenqualitätsfehler als ein Parsing-Fall.
Wer das Pattern in einem ETL-Prozess in mehreren Spalten gleichzeitig braucht, abstrahiert es zu einer benutzerdefinierten Funktion fn_try_convert_money(@p_input nvarchar) — siehe Design Pattern // Sichere Typ-Konvertierung mit T-SQL.
Postgres-Brücke
Postgres bietet zwei Wege, Währungswerte zu speichern — die Wahl fällt zwischen Portabilität und Locale-Komfort:
numeric(19, 4)— die portable Abbildung: Deckt den gesamtenmoney-Wertebereich ab, mit derselben Skala von vier Nachkommastellen und unabhängig vom Session-Locale. Es ist die portable numerische Repräsentation, kein semantisch identischer Geld-Typ — Währung und Formatierung trägt es nicht. Die Empfehlung für ETL-Workloads.money— der Locale-gebundene Postgres-Typ: Währungssymbol, Trennzeichen und Skala folgen der Session-Localelc_monetary. Bei einer deutschen Locale (etwade_DE.UTF-8) erwartet der Cast typischerweise'1.234,56 €', bei einer US-Locale'$1,234.56'— die exakten Formen und Locale-Namen sind system-abhängig. Für portable Workloads nicht empfohlen, weil Format-Drift zwischen Session-Locales das Verhalten fragil macht.
Ein direktes TRY_CONVERT-Pendant, das in einem Aufruf den Zielwert oder NULL liefert, fehlt auch in Postgres 18. Eingebaut ist seit Postgres 16 immerhin die fehlertolerante Validierung über pg_input_is_valid (dazu unten mehr). Der PL/pgSQL-Wrapper unten liefert das NULL-statt-Exception-Verhalten und übernimmt gleich die Komma-Normalisierung und die sichere Leere-String-Semantik des Patterns oben:
1: CREATE OR REPLACE FUNCTION fn_try_cast_numeric_19_4
2: (
3: IN p_input text
4: )
5: RETURNS numeric(19, 4)
6: LANGUAGE plpgsql
7: IMMUTABLE
8: AS $function$
9: BEGIN
10:
11: IF p_input IS NULL OR TRIM(p_input) = '' THEN
12: RETURN NULL;
13: END IF;
14:
15: RETURN CAST(REPLACE(p_input, ',', '.') AS numeric(19, 4));
16:
17: EXCEPTION
18: WHEN invalid_text_representation OR numeric_value_out_of_range THEN
19: RETURN NULL;
20: END;
21: $function$;
22:
23: SELECT fn_try_cast_numeric_19_4('123,45678'); -- 123.4568
24: SELECT fn_try_cast_numeric_19_4(' 123.45 '); -- 123.4500
25: SELECT fn_try_cast_numeric_19_4('1.234.5678'); -- NULL
26: SELECT fn_try_cast_numeric_19_4(''); -- NULL
Der EXCEPTION-Block fängt gezielt die zwei erwartbaren Fehlerklassen: invalid_text_representation für ungültige Darstellungen (etwa den Doppel-Punkt nach einer missglückten Normalisierung) und numeric_value_out_of_range für Overflow. Ein pauschales WHEN OTHERS würde auch unerwartete Fehler still zu NULL machen. Und der Block kostet: Laut Postgres-Doku ist ein BEGIN-Block mit EXCEPTION-Teil deutlich teurer als einer ohne. Für Massen-Imports hilft seit Postgres 16 die eingebaute Validierung: pg_input_is_valid(raw_value, 'numeric(19,4)'), auf die Staging-Spalte angewandt, prüft set-basiert die Konvertierbarkeit ohne fehlschlagenden Cast — pg_input_error_info(…) liefert bei Bedarf die Fehlerdetails. Der Wrapper bleibt das Komfort-Pattern für die Einzelwert-Konvertierung.
Wertebereich- und Skala-Mapping zwischen den Engines:
| T-SQL | Postgres-Abbildung (portabel) | Skala | Bytes (T-SQL / Postgres) |
|---|---|---|---|
money | numeric(19, 4) | Festkomma, Skala 4 | 8 / variabel |
smallmoney | numeric(10, 4) | Festkomma, Skala 4 | 4 / variabel |
decimal(p, s) | numeric(p, s) | Festkomma, Skala s | 5–17 / variabel |
Plattform-übergreifender Hinweis: Postgres-numeric hat keine feste Skala von vier Nachkommastellen wie T-SQL-money — der spezifische money-Pitfall der Zwischen-Rundung tritt dort nicht auf, im gezeigten Beispiel bleibt der Wert vollständig erhalten. Ganz rundungsfrei ist aber auch Postgres nicht: Die Division bestimmt eine endliche Ergebnisskala (1::numeric / 3 liefert standardmäßig 20 Nachkommastellen), Rundung ist also grundsätzlich möglich. Ein unbeschränkt deklariertes numeric unterliegt sehr großen Implementierungsgrenzen (bis zu 131 072 Vorkommastellen und 16 383 Nachkommastellen). Für Cross-DB-Reporting ist das ein wichtiger Konsistenz-Anker und ein zusätzliches Argument gegen den Postgres-money-Typ.
Zusammenfassung
moneyundsmallmoneyspeichern fest vier Nachkommastellen, ihr Wertebereich lässt sich vollständig indecimal(19, 4)beziehungsweisedecimal(10, 4)abbilden. Mehrstufige Berechnungen runden jedes Zwischen-Ergebnis implizit — für Arithmetikdecimal(p, s)bevorzugen.- Bei Text-Eingangswerten wird das Komma nicht als Dezimaltrennzeichen interpretiert, sondern ignoriert, die leere Zeichenfolge wird zu
0.00. Beides fängt das sichere Pattern ab (Komma-REPLACEplusCASE/TRIM). - E-Notation ergibt als Text
NULL, als typisierte Zahl funktioniert sie. Das Pattern lässt sie bewusst außen vor — wer sie im Eingangsschema erlaubt, behandelt sie separat über einenfloat-Zwischenschritt mit Präzisions-Kompromiss. - Postgres:
numeric(19, 4)ist das portable Pendant, der Postgres-eigenemoney-Typ hängt anlc_monetaryund bleibt für ETL fragil. Ein direktes Try-Pendant fehlt,fn_try_cast_numeric_19_4schließt die Lücke (set-basiert hilftpg_input_is_validseit Postgres 16).
Für die Praxis als Entscheidungshilfe:
| Eingangslage | Empfohlener Weg |
|---|---|
| Punkt-Notation, reine Zahl | direkt TRY_CONVERT(money, …) |
| Deutsche Notation (Dezimal-Komma) | Komma normalisieren, dann konvertieren — das sichere Pattern |
| Leere Zeichenfolgen möglich (CSV-Import) | CASE/TRIM mappt auf NULL, dann TRY_CONVERT |
| Tausenderpunkte und Dezimal-Komma gemischt | vorab vollständig bereinigen oder als Datenqualitätsfehler zurückweisen |
| E-Notation in Betrags-Spalten | klären, ob sie zum Eingangsschema gehört — sonst als Datenqualitätsfehler behandeln statt via float normalisieren |
| Mehrstufige Berechnungen (Brutto/Netto, Allokation) | decimal(p, s) statt money für die Arithmetik |
| Cross-Engine-Portabilität | numeric(19, 4) in Postgres, nicht der Postgres-money-Typ |
FAQ
TRY_CONVERT(money, '123,45') 12345.00 zurück und nicht 123.45? Das Komma in einer Text-Eingabe wird von TRY_CONVERT(money, …) nicht als Dezimaltrennzeichen interpretiert, sondern wie ein Gruppierungszeichen ignoriert. Das Verhalten hängt nicht von der Spracheinstellung der SQL-Server-Session ab, auch ein Server mit deutscher Spracheinstellung ändert nichts daran. Bei deutschsprachigen Eingangsdaten muss das Komma vor der Konvertierung via REPLACE(…, ',', '.') durch einen Punkt ersetzt werden — das sichere Pattern oben übernimmt genau das.
0.00 wird? Vor der Konvertierung explizit auf NULL mappen: CASE WHEN TRIM(@p_input) = '' THEN NULL ELSE @p_input END — genau das übernimmt das sichere Pattern. Ohne diese Vorbehandlung macht TRY_CONVERT(money, N'') aus dem leeren Feld eine 0.00, die sich später nicht mehr von einem echten Null-Betrag unterscheiden lässt. Zu beachten: TRIM erkennt nur normale Leerzeichen (char(32)), Tabs oder anderer Unicode-Leerraum brauchen eine erweiterte Normalisierung.
money oder decimal — wann was? money ist für reine Speicher-Spalten und einfache Konvertierungen ohne mehrstufige Arithmetik gut geeignet. Sobald Aggregationen, Divisionen oder Multiplikations-Ketten ins Spiel kommen, führt die implizite Zwischen-Rundung auf vier Nachkommastellen zu akkumulierten Fehlern — dann ist decimal(p, s) mit explizit gewählter Skala die bessere Wahl. Faustregel: money an den Systemgrenzen (Import/Export), decimal für die Verarbeitung. Microsoft selbst rät von money für Berechnungen ab und empfiehlt dafür decimal mit mindestens vier Nachkommastellen. Für neue Berechnungslogik ist decimal(p, s) die robustere Wahl.
(money) 123.45678 / 100 * 100 nicht 123.45678? Bei 123.45678 / 100 bleibt der Ergebnistyp money, dem Zwischen-Ergebnis stehen also nur vier Nachkommastellen zur Verfügung. Im konkreten Beispiel wird 123.45678 / 100 zunächst zu 1.2345 gerundet (statt 1.2345678 zu bleiben), die folgende Multiplikation mit 100 ergibt dann 123.4500 — nicht den Ausgangswert. Bei decimal(p, s) wächst die Skala in der Division, der Wert bleibt in diesem Fall vollständig erhalten.
smallmoney statt money? smallmoney ist auf den Wertebereich ±214 748,3647 begrenzt und belegt nur 4 statt 8 Byte pro Wert. Für Spalten mit garantiert kleinen Werten (Stückpreise, Gebühren, kleinere Beträge) ist das die kompaktere Wahl. Bei jeder Unsicherheit über den maximal möglichen Wert führt der Wechsel auf money zu keinen Nachteilen außer der Speicher-Verdopplung — und vermeidet eine spätere Datentyp-Migration. Für neue Modelle mit Berechnungslogik ist unabhängig davon decimal(p, s) zu erwägen (siehe „money oder decimal“ oben).
TRY_CONVERT(money, …) NULL, obwohl die Zahl gültig aussieht? Die drei häufigsten Ursachen: mehr als ein Punkt im String (typisch nach einer Komma-Ersetzung, wenn die Quelle Tausenderpunkte enthielt), wissenschaftliche Notation als Text und ein smallmoney-Overflow. Eine Gegenprobe mit TRY_CONVERT(money, …) trennt den Overflow-Fall: Liefert sie einen Wert, war der smallmoney-Wertebereich das Problem. Die gefährlicheren Fälle sind allerdings die ohne NULL — das ignorierte Komma und die leere Zeichenfolge erzeugen stille Falschwerte statt eines sichtbaren Fehlersignals.
TRY_CONVERT(money, …)? Für portable Workloads numeric(19, 4) plus der PL/pgSQL-Wrapper fn_try_cast_numeric_19_4 aus der Postgres-Brücke, der die Fehlerklassen invalid_text_representation und numeric_value_out_of_range gezielt zu NULL macht. Der Postgres-eigene money-Typ existiert, hängt aber über lc_monetary am Session-Locale und bleibt für ETL-Workloads fragil.
Verwandte Artikel
ETL-Kontext:
- Datenqualität in einem ETL-Prozess
- ETL vs. ELT — woran du erkennst, welches Muster du wirklich gebaut hast — Makro-Einordnung: ETL vs. ELT als Architektur-Entscheidung, nicht als Reihenfolge der Buchstaben.
TRY_CONVERT für andere Datentypen:
- Datenqualität in SQL Server // TRY_CONVERT für date, datetime, datetime2 und time sicher anwenden
- Datenqualität in SQL Server // TRY_CONVERT für decimal und numeric sicher anwenden
- Datenqualität in SQL Server // TRY_CONVERT für bigint, int, smallint und tinyint sicher anwenden
- Datenqualität in SQL Server // TRY_CONVERT für float und real sicher anwenden
- Datenqualität in SQL Server // TRY_CONVERT für bit sicher anwenden — Ja/Nein-Werte konvertieren
Grundlagen:
- Datenqualität // Grundlagen der Typ-Konvertierung mit T-SQL — CAST, CONVERT, TRY_CAST und TRY_CONVERT im Vergleich.