避免TSQL数据转换错误

时间:2008-10-03 02:44:33

标签: tsql sybase data-conversion

我认为最好以简单的例子的形式提出。下面的SQL块会导致“DB-Library错误:20049严重性:4消息:数据转换导致溢出”消息,但是为什么会这样?

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

工作得很好?

4 个答案:

答案 0 :(得分:4)

上次我尝试使用Sybase(很多年前)时遇到了同样的问题。来自SQL Server的思维模式,我没有意识到Sybase会尝试强制小数 - 这在数学上是应该做的。 :)

来自Sybase manual

  

发生算术溢出错误   新类型的小数点太少了   适合结果的地方。

进一步向下:

  

在隐式转换为数字期间   或十进制类型,规模损失   生成比例错误。使用   arithabort numeric_truncation选项   确定这种错误有多严重   被认为。默认设置,   arithabort numeric_truncation on,   中止导致该语句的语句   错误,但继续处理其他   交易中的陈述或   批量。如果你设置arithabort   numeric_truncation off,自适应   服务器截断查询结果和   继续处理。

因此假设您的方案中可以接受精度损失,您可能需要在事务开始时使用以下内容:

SET ARITHABORT NUMERIC_TRUNCATION OFF

然后在交易结束时:

SET ARITHABORT NUMERIC_TRUNCATION ON

这就是多年前为我解决的问题......

答案 1 :(得分:1)

这只是猜测,但可能是因为DBMS没有查看变量的动态值而只考虑潜在的值?因此,六位十进制数字除以六位十进制数字可能会产生十二进制数字;在字面分区中,DBMS知道没有溢出。但是仍然不确定为什么DBMS会关心 - 它不应该返回两个六位小数除以18位小数的结果吗?

答案 2 :(得分:1)

因为你已经在第一个例子中声明了变量,所以结果应该是相同的声明(即数字(18,6)),但它不是。

我必须说第一个在SQL2005中工作(返回1.000000 [相同的声明类型])而第二个返回(1.00000000000000000000000 [一个不同的声明])。

答案 3 :(得分: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 .

我脑子里应该工作,但不是因为'thenumber'列没有声明(或间接声明为十进制(4,3))。所以你必须使用你想要的格式间接地声明临时表列的比例和精度,就像我的情况是000.000。

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

希望能节省一些时间:)