2009-09-21 418 views
8

當2個十進制數(30,10)在Sql Server 05中分開時,最後2位小數似乎會丟失(甚至不會舍入,只是截斷)。Sql Server小數點(30,10)丟失最後2位小數

例如:

Declare @x decimal(30,10) 
Declare @y decimal(30,10) 
Declare @z decimal(30,10) 

select @x = 2.1277164747 
select @y = 4.8553794574 

Select @z = @y/@x 
select @z 

結果:2.28196731

但是,如果被劃分2號被轉換爲float,似乎工作:

.... 
Select @z = cast(@y as float)/cast(@x as float) 
select @z 

結果:2.28196731

爲什麼Sql會這樣做?在Sql中沒有失去精度的情況下,小數點除法的正確方法是什麼?

+0

這個問題問得好。更奇怪的是,將聲明更改爲(** 38 **,10)實際上使其更糟糕,而將它們更改爲(** 20 **,10)實際上似乎解決了這一問題。沒有意義... – RBarryYoung 2009-09-21 17:08:10

回答

17

SQL Server允許的最大精度爲38.您正在使用十進制(30,10)。如果將此數字除以0.000000001,則最大值爲99,999,999,999,999,999,999.9999999999,否則將以更大的數字結束,因此生成的數據類型必須能夠適應它。這會導致你失去一些精確度。

更改您的原始數據類型爲十進制(20,10)並且不會發生此問題。

有關數據類型(以及他們如何通過數學運算的影響)完整的規則:

Full rules here

+0

這是正確的答案。 SQL Server根據輸入*類型*的精度和比例,而不是輸入*值*,確定結果的精度和比例。因此,結果計算爲十進制(30,8),然後轉換爲十進制(30,10)以存儲在@z中。 – richardtallent 2009-09-21 17:22:49

+0

這是有道理的,但 >>這會導致你失去一些精度<<。如果Sql要舍入到8位小數,那麼它就不會那麼糟糕,但它只會剔除最後2位小數,從而導致錯誤結果。它至少應該給出某種警告,或者甚至在發生這種情況時發生錯誤 – WebMatrix 2009-09-21 17:23:33

+0

有一件事人們似乎錯過了,特別是在對2個最高精度數字進行分割時,縮放比例縮小到6位數。十進制(38,10)/十進制(38,10)=十進制(38,6)。我在某一點上解釋了他們必須這樣做以保護內部工作的精度,以防溢出。 – DaveE 2009-09-21 17:33:18

-1

總之,使用鑄造來保證你的結果。將@x和@y分配給文字值時,它們可能會採用這些文字的精度。這有助於解釋爲什麼按這些值劃分的結果不符合您的期望。

+0

如果您運行_SELECT @ x,@ y_您將看到@x和@y包含所有小數位 – 2009-09-21 17:20:45

+0

@x和@y的文字值被正確存儲,它的結果存儲在@ z被截斷。 – richardtallent 2009-09-21 17:24:27

+0

@所有......感謝您的澄清。 – 2009-09-21 17:43:30