Tag: "konvertierung"

Leere Strings und implizite Datentyp Konvertierung

Posted on Aug 27, 2010 von in SQL Server

Angenommen wir haben folgende Ausgangssituation:

Ganze Geschichte »

FLOAT Daten in VARCHAR konvertieren

Posted on Aug 2, 2005 von in SQL Server

Die Konvertierung von FLOAT Daten in CHAR oder VARCHAR im SQL Server 2000 kann unter Umständen für Überraschungen sorgen, die mehr oder weniger unangenehm sind. Mal angenommen wir finden einen gültigen Grund, warum wir FLOAT in VARCHAR umwandeln wollen und haben folgende Basisdaten

CREATE TABLE t1
(
Preis FLOAT
)
INSERT INTO t1 SELECT 0.99
UNION ALL SELECT 9.99
UNION ALL SELECT 99.99
UNION ALL SELECT 999.99
UNION ALL SELECT 9999.99

Die Abfrage, die diese Daten umwandeln soll, sieht folgendermaßen aus:

SELECT 
CAST(Preis AS VARCHAR(10)) Preis
FROM t1

Preis
----------
0.99
9.99
99.99
999.99
9999.99

(5 row(s) affected)

So, kein Problem bisher. Nun betrachten wir einmal folgende Basisdaten:

INSERT INTO t1 SELECT 10000
UNION ALL SELECT 10000.49
UNION ALL SELECT 10000.5
UNION ALL SELECT 10000.51
UNION ALL SELECT 10000.99

SELECT
CAST(Preis AS VARCHAR(10)) Preis
FROM t1

Preis
----------
10000
10000.5
10000.5
10000.5
10001

(5 row(s) affected)

Es sieht ganz danach aus, als ob SQL Server 2000 ab 10000 intern eine Rundung vornimmt. Etwas in der Form.

SELECT 
CAST(Preis AS VARCHAR(10)) Preis
, CONVERT(VARCHAR, Preis,0) FROM t1 Preis ---------- ------------------------------ 10000 10000 10000.5 10000.5 10000.5 10000.5 10000.5 10000.5 10001 10001 (5 row(s) affected)

So, wie kriegt man es nun hin, daß auch die Daten heraus kommen, die eingegeben wurden?
Eine Möglichkeit besteht darin, die Daten erst explizit in DECIMAL umzuwandeln und anschließend zurück in VARCHAR. Etwa so:

SELECT 
CAST(Preis AS VARCHAR(10)) Preis
, CONVERT(VARCHAR, Preis,0)
, CAST(CAST(PREIS AS DECIMAL(8,2)) AS VARCHAR(20)) FROM t1 Preis ---------- ------------------------------ -------------------- 10000 10000 10000.00 10000.5 10000.5 10000.49 10000.5 10000.5 10000.50 10000.5 10000.5 10000.51 10001 10001 10000.99 (5 row(s) affected)

Eine weitere Möglichkeit wäre:

SELECT 
CAST(Preis AS VARCHAR(10)) Preis
, CONVERT(VARCHAR, Preis,0)
, CAST(CAST(PREIS AS DECIMAL(8,2)) AS VARCHAR(20))
, LTRIM(RTRIM(STR(ROUND(Preis,2),10,2)))
FROM t1

Preis
---------- ------------------------------ -------------------- ----------
10000 10000 10000.00 10000.00
10000.5 10000.5 10000.49 10000.49
10000.5 10000.5 10000.50 10000.50
10000.5 10000.5 10000.51 10000.51
10001 10001 10000.99 10000.99

(5 row(s) affected)

Diese Methode geht nicht den Umweg über die explizite Konvertierung in einen anderen Datentypen. STR() wandelt FLOAT direkt um. Das RTRIM() ist zwar nicht zwingend notwendig, aber schadet auch nicht wirklich.

Warum zeigt SQL Server dieses Verhalten? Ehrlich gesagt, habe ich darauf keine Antwort. Eventuell könnte Single und Double Precision beim FLOAT Datentyp eine Rolle spielen, aber dies ist nur eine Vermutung. Falls jemand eine schlüssige Begründung für dieses Verhalten hat, würde ich micht freuen, diese zu hören.