2008-10-03 125 views
4

我認爲這是一個簡單示例的最佳形式。以下SQL塊導致「DB-Library錯誤:20049嚴重性:4消息:數據轉換導致溢出」消息,但是怎麼回事?避免TSQL數據轉換錯誤

declare @a numeric(18,6), @b numeric(18,6), @c numeric(18,6) 
select @a = 1.000000, @b = 1.000000, @c = 1.000000 
select @a/(@b/@c) 
go 

這是怎麼回事什麼不同來:

select 1.000000/(1.000000/1.000000) 
go 

工作正常?

+0

我不知道,如果這增加了什麼,但選擇會發生什麼(@一* @ B)/ @ç這是代數相同。 – wcm 2008-10-03 22:57:56

回答

4

我上次嘗試使用Sybase(多年前)時遇到了同樣的問題。從SQL Server的思想來看,我沒有意識到Sybase會試圖強制小數 - 這在數學上應該是應該是。 :)

Sybase manual

Arithmetic overflow errors occur when the new type has too few decimal places to accommodate the results.

進一步回落:

During implicit conversions to numeric or decimal types, loss of scale generates a scale error. Use the arithabort numeric_truncation option to determine how serious such an error is considered. The default setting, arithabort numeric_truncation on, aborts the statement that causes the error but continues to process other statements in the transaction or batch. If you set arithabort numeric_truncation off, Adaptive Server truncates the query results and continues processing.

所以假設的精度損失是在方案可以接受的,你可能想在以下您的交易開始:

SET ARITHABORT NUMERIC_TRUNCATION OFF 

然後在你的交易結束:

SET ARITHABORT NUMERIC_TRUNCATION ON 

這就是那些很多年前解決了這個問題對我來說...

1

這只是推測,但是它可能是DBMS不會查看變量的動態值,而只是查看潛在值?因此,六位十進制數字除以六位十進制數字可能會導致十二進制數字;在文字劃分中,DBMS知道沒有溢出。仍然不確定爲什麼DBMS會關心,但是不應該將兩個六位十進制的結果返回到十八進制數字嗎?

1

因爲您已經在第一個示例中聲明瞭變量,所以預期結果是相同的聲明(即數字(18,6)),但它不是。

我不得不說第一個工作在SQL2005雖然(返回1.000000 [相同的聲明類型]),而第二個返回(1.00000000000000000000000 [一個完全不同的聲明])。

0

沒有直接關係,但有些時候也能拯救別人與算術使用Sybase ASE(12.5.0.3)發生溢出錯誤。

我在一個臨時表中設置了一些默認值,我打算稍後更新,並且偶然發現了一個算術溢出錯誤。

declare @a numeric(6,3) 

select 0.000 as thenumber into #test --indirect declare 

select @a = (select thenumber + 100 from #test) 

update #test set thenumber = @a 

select * from #test 

顯示錯誤:

Arithmetic overflow during implicit conversion of NUMERIC value '100.000' to a NUMERIC field . 

這在我的頭應該工作,但不作爲「數量寫」列未聲明(或間接地聲明爲十進制(4,3) )。因此,您必須按照您想要的格式間接聲明臨時表格列的比例和精度,在我的情況下爲000.000。

select 000.000 as thenumber into #test --this solved it 

希望這可以節省有人一段時間:)