2008-10-03 117 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 

希望这可以节省有人一段时间:)