詳細(xì)分析sqlserver中的小數(shù)類型(float和decimal)
在SQL Server中實(shí)際上只有兩種小數(shù)數(shù)值類型,分別是float(近似數(shù)值)和decimal(精確數(shù)值),這兩種類型能表示所有的小數(shù)數(shù)值類型。
float(近似數(shù)值類型)
float表示的是近似數(shù)值,存在一定的精度缺失。
float(n)
這里的n是以科學(xué)計(jì)數(shù)法存儲(chǔ)浮點(diǎn)數(shù)尾數(shù)的位數(shù),因此此參數(shù)決定了精度和存儲(chǔ)的大小。其是可選的,默認(rèn)值是53,即float等價(jià)于float(53),占用8bytes。如果指定了n,則它必須是介于1至53之間的值。實(shí)際上,雖然n的取值范圍定義是1至53,但實(shí)際上float只能表示float(53)和float(24)兩種類型,分別占用8bytes和4bytes。
n的范圍 | 精度 | 存儲(chǔ)大小 |
1-24(都視為24) | 7位小數(shù) | 4bytes |
25-53(都視為53) | 15位小數(shù) | 8bytes |
使用近似數(shù)值要格外注意盡量避免相等比較,因?yàn)楸热?可以被存儲(chǔ)為1.000000056,也可以被存儲(chǔ)為1.00000000672,進(jìn)行相等比較會(huì)得到意料之外的結(jié)果。
decimal(精確數(shù)值類型)
decimal表示的是精確數(shù)值類型。不存在精度損失,別名是numeric。
decimal(p, s)
-- 等價(jià)于
numeric(p, s)
精確數(shù)值類型需要分別指定小數(shù)的最大位數(shù)(p)和小數(shù)位的數(shù)量(s):
- p(precision):指定小數(shù)的最大位數(shù),小數(shù)點(diǎn)的左側(cè)和右側(cè)的數(shù)字的總數(shù)量不能超過p,p的取值范圍是從1到38,默認(rèn)值為18。
- s(scale):指定在小數(shù)點(diǎn)右側(cè)的小數(shù)位數(shù),p-s是小數(shù)點(diǎn)左邊的最大位數(shù)。s必須是從0到p的值,只有在指定了精度的情況下才能指定s,s的默認(rèn)值是0,因此,0 <= s <= p。
p的大小也同時(shí)決定了存儲(chǔ)位數(shù)的大小:
精度大小 | 存儲(chǔ)位數(shù) |
1-9 | 5 |
10-19 | 9 |
20-28 | 13 |
29-38 | 17 |
因?yàn)閜和s必須遵守規(guī)則:0 <= s <= p <= 38,所以decimal(p, s)實(shí)際上能夠表示的有效值是從-10^38+1到10^38-1。這就意味著,decimal數(shù)據(jù)類型的最大精度是38,即最多可以存儲(chǔ)38位數(shù)字,所有這些數(shù)字均可位于小數(shù)點(diǎn)后面。decimal數(shù)據(jù)類型存儲(chǔ)精確的數(shù)字表示形式,沒有近似值。
小數(shù)的除法
小數(shù)的除法實(shí)際上是近似運(yùn)算,因此在使用除法的時(shí)候SQL Server會(huì)自動(dòng)將小數(shù)的類型提升為float類型(隱式數(shù)據(jù)類型升級(jí))。
小數(shù)常量的默認(rèn)數(shù)據(jù)類型是decimal,但是float類型的優(yōu)先級(jí)比decimal類型要高。在默認(rèn)的情況下,SQL Server會(huì)將小數(shù)數(shù)值的常量自動(dòng)轉(zhuǎn)換為decimal數(shù)據(jù)類型(常態(tài)下),而在進(jìn)行小數(shù)的除法運(yùn)算的時(shí)候,則會(huì)就近進(jìn)行數(shù)據(jù)類型的升級(jí),轉(zhuǎn)換為float(24)或float(53)數(shù)據(jù)類型(運(yùn)算時(shí))。
簡單舉個(gè)例子,常量12.345在常態(tài)下會(huì)被解析并轉(zhuǎn)換為numeric(5, 3)的數(shù)值類型,即使用最小精度5和最小小數(shù)位數(shù)3;而在運(yùn)算除法時(shí),比如12.345/2則會(huì)被解析并轉(zhuǎn)換為float(24),即最小精度的近似數(shù)值類型。
小數(shù)轉(zhuǎn)為字符串
相比cast(float_expression as float(24/53)),使用str()函數(shù)更能夠有效控制近似數(shù)值的小數(shù)位數(shù),因?yàn)閟tr()函數(shù)獲取的是近似數(shù)值。
str(float_expression [ , length [ , decimal ] ])
str()函數(shù)可以接受length、decimal兩個(gè)參數(shù),皆是可選的。
- length是小數(shù)的總位數(shù),包含正負(fù)符號(hào),小數(shù)點(diǎn),小數(shù)點(diǎn)左邊和右邊數(shù)字個(gè)數(shù)之和;
- decimal是小數(shù)位的數(shù)量(小數(shù)點(diǎn)右邊數(shù)字個(gè)數(shù)),小數(shù)位最大為16位,不能超過16,否則,會(huì)被截?cái)酁?6位。如果小數(shù)位沒有decimal多,那么右邊補(bǔ)0。
- 返回值是varchar類型。
將decimal常量轉(zhuǎn)換為varchar類型:
select str(123.45, 10, 2); -- 123.45
將float表達(dá)式的值轉(zhuǎn)換為varchar類型(位數(shù)不足自動(dòng)補(bǔ)0):
select str(1.0/3, 10, 8); -- 0.33333300
對(duì)小數(shù)常量轉(zhuǎn)換為varchar類型,減少小數(shù)位的數(shù)量,由2位減少為1位(會(huì)自動(dòng)進(jìn)行四舍五入運(yùn)算):
select str(123.45, 6, 1); -- 123.5
使用函數(shù)str或cast將float和decimal強(qiáng)制轉(zhuǎn)換為varchar類型時(shí),返回的數(shù)值可能是不相同的:
select str(56.64564684439527, 38, 20); -- 56.64564684438742000000 select cast(56.64564684439527 as varchar(100)); -- 56.64564684439527
這是因?yàn)閮煞N函數(shù)的處理方式的不同導(dǎo)致的:str()函數(shù)會(huì)對(duì)小數(shù)數(shù)值先取近似值;而cast()函數(shù)則是返回與原始值數(shù)據(jù)類型相同的值(decimal返回精確值,float返回近似值)。
以上就是詳細(xì)分析sqlserver中的小數(shù)類型(float和decimal)的詳細(xì)內(nèi)容,更多關(guān)于sqlserver 小數(shù)類型的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SQL?Server?Reporting?Services?匿名登錄的問題及解決方案
這篇文章主要介紹了關(guān)于?SQL?Server?Reporting?Services?匿名登錄的解決方案,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-09-09SQL中concat、concat_ws()、group_concat()的使用與區(qū)別
本文主要介紹了SQL中concat、concat_ws()、group_concat()的使用與區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05SQL Server 復(fù)制需要有實(shí)際的服務(wù)器名稱才能連接到服務(wù)器
今天在做sql Server 2005的實(shí)驗(yàn)的時(shí)候碰到的問題,問題描述很清楚,懷疑是我以前給計(jì)算機(jī)修改了名稱而導(dǎo)致的.可以用select @@servername和select serverproperty ('servername')對(duì)照一下,兩個(gè)的結(jié)果是否一樣2012-06-06SQL?Server使用表值參數(shù)的實(shí)現(xiàn)示例
表值參數(shù)提供了一種將多行數(shù)據(jù)作為參數(shù)傳遞給存儲(chǔ)過程或函數(shù)的方法,本文主要介紹了SQL?Server使用表值參數(shù)的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下2024-08-08不同數(shù)據(jù)庫之間導(dǎo)入導(dǎo)出功能介紹
在SQL Server中使用最廣泛的就是通過SELECT INTO語句導(dǎo)出數(shù)據(jù),SELECT INTO語句同時(shí)具備兩個(gè)功能2010-12-12SQL Server數(shù)據(jù)庫設(shè)置自動(dòng)備份策略的完整步驟
這篇文章主要給大家介紹了關(guān)于SQL Server數(shù)據(jù)庫設(shè)置自動(dòng)備份策略的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用sql server具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-09-09SQL Server 聚集索引和非聚集索引的區(qū)別分析
聚集索引:物理存儲(chǔ)按照索引排序 非聚集索引:物理存儲(chǔ)不按照索引排序2011-07-07