TRY_CONVERT // Konvertierung nach money, smallmoney

SQL Server stellt für die Speicherung von Währungswerten die folgenden Datentypen zur Verfügung:

  • money
  • smallmoney

Der Datentyp money ist bezüglich der gespeicherten Werte im Wesentlichen identisch zu dem Datentyp decimal(19, 4) und der Datentyp smallmoney zu decimal(10, 4). Es gibt intern Unterschiede, wie SQL Server einen decimal-Wert und einen money/smallmoney-Wert speichert. Diese Unterschiede sind hier jedoch nicht relevant.

Die Datentypen money und smallmoney weisen eine Besonderheit in Berechnungen auf. So wird das Ergebnis einer Multiplikation oder Division von money-Werten nach jedem Teilschritt der Berechnung implizit in einen money Wert mit 4 Nachkom­mastellen konvertiert.

 1: SELECT CAST(123.45678 AS money        )              -- 123,4568
 2: SELECT CAST(123.45678 AS money        ) / 100        -- 1,2345
 3: SELECT CAST(123.45678 AS money        ) / 100 * 100  -- 123,45
 4:                                                     -- 
 5: SELECT CAST(123.45678 AS decimal(10,4) )             -- 123.4568
 6: SELECT CAST(123.45678 AS decimal(10,4) ) / 100       -- 1.23456800
 7: SELECT CAST(123.45678 AS decimal(10,4) ) / 100 * 100 -- 123.45680000

Bei der Verwendung des Datentyps money verliert das Ergebnis in der ersten Anweisung an Genauigkeit. Das Ergebnis in den Zeilen 1 und 3 ist nominell nicht gleich. Bei Verwendung des Datentyps decimal erhält man das gleiche Ergebnis.

Das Rückgabeergebnis der Konvertierung eines Wertes in den Datentyp money hängt davon ab, in welchem Datentyp eine Zahl übergeben wird. Zu unterscheiden ist hier die Übergabe eines Parameters expression als Wert vom Typ Text und als Wert vom Typ Kein Text.

Inhalt

Text

Wird ein Wert vom Typ Text übergeben, so muss der übergebene Wert eine Zahl darstellen. Als Dezimaltrennzeichen wird immer ein Punkt erwartet. Kommas werden im Gegensatz zu der Konvertierung einer Zahl in den Datentypen decimal ignoriert. Da Dezimalzahlen, die über eine Textdatei ge­liefert werden, zum Beispiel in Deutscher Notation ein Komma als Dezimaltrennzeichen verwenden, ist das Kommas generell durch einen Punkt zu ersetzen. Enthält der Eingangswert sowohl ein Dezimal­trenn­zeichen als auch Kommas als Tausender­trenn­zeichen, führt diese Ersetzung dazu, dass der Eingangswert nicht interpretiert werden kann, da der Eingangswert dann mehr als einen Punkt aufweist. Das Ergebnis der Konvertierung ist in diesem Fall ein NULL.

Führende und folgende Leerzeichen werden von der Funktion abgeschnitten und verhin­dern nicht die Konvertierung. Ein leerer String wird im Gegensatz zu dem Zieldatentyp decimal als 0 übersetzt. Enthält der Eingangswert mehr als 4 Nachkommastellen, führt die Funktion TRY_CONVERT eine Rundung auf die vierte Nachkommastelle durch.

Das folgende Code-Beispiel zeigt die Ergebnisse der TRY_CONVERT Funktion für verschiedene gültige, ungültige und teilweise auch unsinnige Dezimal­zahlen, die als Text vom Typ nvarchar übergeben und in eine Zahl vom Typ money konvertiert werden:

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 

Wird ein Wert vom Typ Text an die Funktion TRY_CONVERT übergeben, so muss der übergebene Wert eine Zahl darstellen. Als Dezimaltrennzeichen wird immer ein Punkt erwartet. Tausendertrennzeichen sind nicht zulässig. Enthält der Parameter ein Komma, so kann der Wert nicht konvertiert werden und die Funktion TRY_CONVERT liefert NULL zurück. Führende und folgende Leer­zeichen werden von der Funktion TRY_CONVERT abge­schnitten und verhin­dern nicht die Konvertierung. Ein leerer String wird als NULL übersetzt.

Das folgende Code-Beispiel zeigt die Ergebnisse der TRY_CONVERT Funktion für verschiedene gültige und ungültige Dezimalzahlen, die als Text vom Typ nvarchar übergeben und in eine Zahl vom Typ money konvertiert werden:

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 

Besondere Beachtung erfordern die Zeilen 10 bis 15. Hier werden zum Teil unsinnige Kombinationen von Dezimal­trenn­zeichen und Tausender­trenn­zeichen verwendet, um das Verhalten der Funktion TRY_CONVERT zu erläu­tern.

In den Zeilen 5 und 6 sind die Eingangswerte eine leere Zeichenfolge bzw. ein Text mit nur Leerzeichen. Die Funktion TRY_CONVERT konvertiert diese zu dem Wert 0. Dieses Verhalten kann als Fehler in der Funktion TRY_CONVERT angesehen werden und ist bei der Konvertierung dahin­gehend zu berücksichtigen, dass eine leere Zeichenfolge bzw. ein Text mit nur Leerzeichen vor der Konvertierung durch ein NULL zu ersetzen ist.

Kein Text

Wird eine Zahl nicht als Text, sondern als eine typisierte Zahl übergeben, kann die Funktion jede beliebige Zahl in einen Wert vom Typ money konvertieren. Werte werden auf die vierte Nachkommastelle gerundet. Die Konver­tie­rung eines Zahl­wertes in den Zieldatentyp money kann damit den nominalen Ausgangswert ändern.

Das folgende Code-Beispiel zeigt die Ergebnisse der TRY_CONVERT Funktion für verschiedene gültige und ungültige Zahlen, die als typisierte Werte übergeben und jeweils in eine Zahl vom Typ money konvertiert werden:

 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 

Zu beachten ist hier, dass die Zahl in der Zeile 3 keine Dezimalzahl ist. Der Wert hinter dem Komma wird als style-Parameter interpretiert, der jedoch keinen Effekt auf die Typ-Konvertierung hat. In dieser Zeile ist der Wert in expression vom Typ int. In der Zeile 4 wird in expression eine Dezimal­zahl mit Nachkommastellen als Wert vom Typ float übergeben.

Sichere Typ-Konvertierung

Unter Berücksichtigung der obigen Ausführungen, insbesondere des fehlerhaften Verhaltens der Funktion TRY_CONVERT bei der Konvertierung einer leeren Zeichenfolge bzw. eines Textes mit nur Leerzeichen, wird die Konvertierung eines Eingangswertes in den Datentyp money über die folgende Anweisung durchgeführt:

 1: TRY_CONVERT( [money[(n)]|smallmoney]
 2:             ,TRY_CONVERT( float
 3:                          ,REPLACE( CASE WHEN TRIM([Input]) = ''
 4:                                       THEN NULL 
 5:                                       ELSE [Input] 
 6:                                    END
 7:                                   , ','
 8                                    , '.'
 9:                                  )
10:                         )
11:            ) AS [Output]

Und hier ein Beispiel für die Anwendung…

 1: DECLARE @input as nvarchar(30);
 2: SET @input = '  123.45678';
 3: SELECT TRY_CONVERT(
 4:            money
 5:           ,TRY_CONVERT( float
 6:                        ,REPLACE( CASE WHEN TRIM(@input) = ''
 7:                                     THEN NULL 
 8                                      ELSE @input
 9:                                  END
10:                                 , ','
11:                                 , '.'
12:                                )
13:                       )
14:            ) AS [Output] 

Zusammenfassung

Bei der Konvertierung eines Wertes in den Datentyp money sind gleich mehrere Sonderfälle zu berücksichtigen: Leere Zeichenfolgen werden zu der Zahl 0 konvertiert, Zahlen in wissenschaftlicher Notation können nicht konvertiert werden, Tausender Trennzeichen sind nicht zulässig und als Dezimaltrennzeichen ist nur der Dezimalpunkt erlaubt. Die hier gezeigte Anweisung berücksichtigt diese Sonderfälle bei der Konvertierung eines Wertes in den Datentyp money.

Die oben beschriebene Rundungsproblematik spielt zwar bei der Konvertierung eines Wertes in einem ETL-Prozess eine untergeordnete Rolle, bei Berechnungen, die in einem ETL-Prozess mit money-Werten durchgeführt werden, ist diese jedoch zu berücksichtigen und gegebenenfalls der Datentyp decimal dem Datentyp money vorzuziehen.

Verwandet Artikel