在SQL Server中,實際上小數數值只有兩種數據類型:float 和 decimal,分別是近似數值和精確數值。其餘小數類型,均可以使用float和decimal來替代,例如,雙精度(double precision)數據類型等價於 float(53),real等價於float(24),numeric是 decimal的同義詞,應該避免在程序中直接使用 double precision、real和numeric,而是用 float(24) 、float(53)和decimal 代替。html
float是近似數值,存在精度缺失;decimal是精確數值,不存在精度損失。當數值不容許精度丟失時,使用 decimal數據類型存儲數據。在計算小數的除法時,SQL Server 內部隱式升級數據類型,根據小數數值的數據類型,就近向float(24) 或float(53)轉換。git
float 表示近似數值,存在精度損失,數據類型是 float(n),n是可選的,默認類型是float(53),佔用8bytes。雖然n的取值範圍是1-53,實際上,float 只能表示兩種類型float(53) 和 float(24),分別佔用 8Bytes 和 4Bytes。express
其中n是以科學計數法存儲浮點數尾數的位數,所以決定了精度和存儲大小。 若是指定了n,則它必須是介於1和53之間的值,n的缺省值是53。app
decimal不存在精度損失,數據類型decimal(p,s) 須要分別指定小數的最大位數(p)和小數位的數量(s):
p 和 s 必須遵照規則:0 <= s <= p <= 38,decimal(p,s) 可以表示的有效值是從 - 10^38 +1 到 10^38 - 1。
decimal 數據類型的最大精度爲 38,這意味着,decimal 數據類型最多能夠存儲 38位數字,全部這些數字都可位於小數點後面。decimal 數據類型存儲精確的數字表示形式,沒有近似值。
小數的除法是近似計算,必須把小數的類型提高爲float類型。小數常量的默認數據類型是decimal,float的優先級比decimal高。
在Transact-SQL語句中,具備小數點的常量會自動轉換爲decimal,並使用必需的最小精度和小數位數。 例如,將常量12.345轉換爲小數類型,decimal(5,3),即精度爲5,小數位爲3。
在TSQL中,小數常量是decimal類型,如一下示例,TSQL把常量 1.0 自動轉換爲decimal(2,1),在計算除法時,TSQL自動把decimal轉換位float類型。
declare @f_low float(24) declare @f_high float(53) select @f_low=cast(1.0 as float(24))/3,@f_high=cast(1.0 as float(53))/3 select 1.0/3 as f,@f_low as f_low, @f_high as f_high
declare @dec decimal(38,37) declare @num decimal(38,37) select @dec=cast(1.0 as decimal(38,37))/3,@num=cast(1.0 as decimal(38,37)) select @dec,@num,1.0/3,cast(1.0 as float(24))/3,1.000000000000/3,cast(1.0 as float(53))/3
默認狀況下,SQL Server將小數常量做爲decimal 數據類型,在計算小數的除法時,就近進行數據類型的升級,轉換爲float(24)或float(53) 數據類型。
在 Transact-SQL 語句中,小數數值的常量自動轉換爲 decimal 數據類型,在轉換時,使用最小的精度和小數位數。例如,常量 12.345 被轉換爲 numeric 值,其精度爲 5,小數位爲 3。
In Transact-SQL statements, a constant with a decimal point is automatically converted into a numeric data value, using the minimum precision and scale necessary. For example, the constant 12.345 is converted into a numeric value with a precision of 5 and a scale of 3.
相比cast(float_expression as float(24/53)),使用 str 函數可以有效控制近似數值的小數位數,函數str獲取的是近視數值。
STR ( float_expression [ , length [ , decimal ] ] )
1,對小數常量轉換爲varchar類型,減小小數位的數量,由2位減小爲1位。
SELECT STR(123.45, 6, 1);
2,將decimal 變量轉換爲varchar類型
declare @d decimal(10,2) set @d=123.45 SELECT STR(@d, 6, 1);
3,將 float 表達式的值轉換爲varchar 類型
1.0/3 默認轉換爲float(24) 類型,所以只有6位小數,小於decimal 參數的8位,右邊補兩個0。
SELECT STR(1.0/3, 10, 8);
4,在將float和decimal轉換爲varchar類型時,使用函數str或cast強制轉換,返回的數值多是不相同
declare @dt decimal(38,30) declare @df float(53) set @dt=50.8863983154297 set @df=50.8863983154297 select @df as df,@dt as dt, str(@dt,38,30) as str_dt,str(@df,38,30) as str_df, cast(@dt as varchar(100)) as var_dt,cast(@df as varchar(100)) as var_df
字段str_dt和str_df的值是不相同的,str函數首先對這兩個小數數值取近似值,使用cast強制轉換,對於decimal,返回的是精確值,對於float,返回的是近似值。