Inhalt
- Überblick
- Text
- Kein Text
- Decimal vs. float
- Sichere Typ-Konvertierung
- Zusammenfassung
- Verwandte Artikel
Überblick
SQL Server stellt für die Speicherung von Gleitkommazahlen die folgenden Datentypen zur Verfügung:
- float(n)
- real
Die Datentypen float und real sind keine präzisen Datentypen. Sie eignen sich für die Speicherung besonderes großer oder kleiner Werte, jedoch zu Lasten der Genauigkeit. Damit kann augenscheinlich eine Zahl gleich 0 gespeichert sein, die jedoch in einer weniger signifikanten und nicht angezeigten Stelle hinter dem Komma einen Wert ungleich 0 hat. Sie finden überwiegend in technischen Applikationen, in denen Messwerte und technische Daten zu speichern sind, Anwendung.
Die Datentypen float und real unterscheiden sich durch die Präzision, mit der eine Dezimalzahl gespeichert wird. Der Datentyp float erwartet einen optionalen Parameter n, der die Anzahl der Bits angibt, die für die Speicherung der Mantisse (Zahl vor dem Exponenten) verwendet wird. Zulässig sind hier die Werte 1 bis 53. Bei einer Zahl kleiner oder gleich 24 belegt ein float Wert 4 Byte Speicherplatz. Bei einer Zahl größer 24 belegt ein float Wert 8 Byte Speicherplatz. Der Datentyp real ist äquivalent zu float(24). Fehlt die Angabe der Präzision, nimmt SQL Server den Wert 53 an. Dieser Artikel betrachtet ausschließlich den Datentyp float ohne Angabe des Parameters n. Ein eigener Abschnitt befasst sich mit der Auswirkung der Präzision der Datentypen decimal und float.
Wie bereits bei den anderen beschriebenen Datentypen, erfolgt auch hier eine Unterscheidung, ob der zu konvertierende Wert als Text oder als typisierte Zahl übergeben wird.
Text
Wird in dem Parameter expression ein Wert vom Typ Text ü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. Da Dezimalzahlen, die über eine Textdatei geliefert werden, gelegentlich ein Komma als Dezimaltrennzeichen verwenden, sind Kommas generell durch einen Punkt zu ersetzen.
Führende und folgende Leerzeichen werden von der Funktion abgeschnitten und verhindern nicht die Konvertierung. Ein leerer String wird im Gegensatz zu dem Zieldatentyp decimal als 0 übersetzt. Die Konvertierung einer Zahl in wissenschaftlicher Notation wird unterstützt. Eine Rundung des konvertierten Wertes findet nicht statt. 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 float konvertiert werden:
1: SELECT TRY_CONVERT(float, NULL ) -- > NULL
2: SELECT TRY_CONVERT(float, N'123' ) -- > 123
3: SELECT TRY_CONVERT(float, N'123,456' ) -- > NULL
4: SELECT TRY_CONVERT(float, N'123.456' ) -- > 123.456
5: SELECT TRY_CONVERT(float, N'' ) -- > 0
6: SELECT TRY_CONVERT(float, N' ' ) -- > 0
7: SELECT TRY_CONVERT(float, N' 123.456') -- > 123.456
8: SELECT TRY_CONVERT(float, N'123.456 ') -- > 123.456
9: SELECT TRY_CONVERT(float, N'123456E-3') -- > 123.456
Besondere Beachtung erfordern die Zeilen 3, 5 und 6. Der Eingangsparameter in der Zeile 3 enthält als Dezimaltrennzeichen ein Komma und kann daher nicht konvertiert werden. Ist der Eingangswert, wie in den Zeilen 5 und 6 notiert, eine leere Zeichenfolge bzw. ein Text mit nur Leerzeichen, konvertiert die Funktion TRY_CONVERT diesen zu dem Wert 0. Dieses Verhalten kann als Fehler in der Funktion TRY_CONVERT angesehen werden und ist bei der Konvertierung dahingehend 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 in expression eine Zahl nicht als Text, sondern als eine typisierte Zahl übergeben, kann die Funktion jede beliebige Zahl in einen Wert vom Typ float konvertieren. Eine Rundung erfolgt nicht. 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 float konvertiert werden:
1: SELECT TRY_CONVERT(float, NULL ) -- > NULL
2: SELECT TRY_CONVERT(float, 123 ) -- > 123
3: SELECT TRY_CONVERT(float, 123,456 ) -- > 123
4: SELECT TRY_CONVERT(float, 123.456 ) -- > 123.456
5: SELECT TRY_CONVERT(float, 123456E-3) -- > 123.456
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.
decimal vs. float
Decimal ist im Unterschied zu den Datentypen float und real ein präziser Datentyp, bei dem die Anzahl der Nachkommastellen angegeben werden kann und die Nachkommastellen exakt gespeichert werden.
Selbst einfache Berechnungen wie die Addition und Subtraktion von float-Werten können zu einem ungewünschten Ergebnis führen. In dem folgenden Code-Beispiel wird als Ergebnis der Zeilen 5 und 12 der Wert 0 erwartet. Während das Ergebnis bei Verwendung von decimal-Variablen exakt ist, erhalten wir bei Verwendung des Datentyps float lediglich eine Annäherung an den Wert 0.
1: DECLARE @f1 AS float = 2; --
2: DECLARE @f2 AS float = 3.4; --
3: DECLARE @f3 AS float = @f1 + @f2; --
4:
5: SELECT @f3 - @f2 - @f1 -- > 4.44089209850063E-16
6: -- > 0,0000000000000004440892...
7:
8: DECLARE @d1 AS decimal(2,1) = 2; --
9: DECLARE @d2 AS decimal(2,1) = 3.4; --
10: DECLARE @d3 AS decimal(2,1) = @d1 + @d2;--
11:
12: SELECT @d3 - @d2 - @d1 -- > 0.0
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 float über die folgende Anweisung durchgeführt:
1: TRY_CONVERT( [float(n)|real]
2: ,REPLACE( CASE WHEN TRIM([Input]) = ''
3: THEN NULL
4: ELSE [Input]
5: END
6: , ','
7: , '.'
8: )
9: ) 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: float
5: ,REPLACE( CASE WHEN TRIM(@input) = ''
6: THEN NULL
7 ELSE @input
8: END
9: , ','
10: , '.'
11: )
12: ) AS [Output]
Zusammenfassung
Bei der Konvertierung eines Wertes in den Datentyp float gibt es zwei Sonderfälle zu berücksichtigen: Leere Zeichenfolgen werden zu der Zahl 0 konvertiert, Tausender Trennzeichen sind nicht zulässig und als Dezimaltrennzeichen ist nur der Dezimalpunkt erlaubt. Die oben gezeigte sichere Konvertierung eines Wertes in den Datentyp float berücksichtigt diese Sonderfälle.
Der oben beschriebene Unterschied zwischen den Datentypen decimal und float spielt zwar bei der Konvertierung eines Wertes in einem ETL-Prozess eine untergeordnete Rolle, bei Berechnungen, die in einem ETL-Prozess mit float-Werten durchgeführt werden, ist diese jedoch zu berücksichtigen und gegebenenfalls der Datentyp decimal dem Datentyp float vorzuziehen.
Verwandet Artikel
- Datenqualität in einem ETL-Prozess
- Datenqualität // Grundlagen der Typ-Konvertierung mit T-SQL
- TRY_CONVERT // Konvertierung nach bigint, int, smallint, tinyint
- TRY_CONVERT // Konvertierung nach decimal oder numeric
- TRY_CONVERT // Konvertierung nach money, smallmoney
- TRY_CONVERT // Konvertierung nach float, real
- TRY_CONVERT // Konvertierung nach bit
- TRY_CONVERT // Konvertierung nach date, datetime, datetime2, time