避免TSQL数据转换错误

避免TSQL数据转换错误,tsql,sybase,data-conversion,Tsql,Sybase,Data Conversion,我认为最好用一个简单的例子来说明这一点。下面的SQL块会导致“DB库错误: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 哪

我认为最好用一个简单的例子来说明这一点。下面的SQL块会导致“DB库错误: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

哪种方法可以很好地工作?

这只是猜测,但是否DBMS不会查看变量的动态值,而只查看潜在值?因此,一个六进制数字除以一个六进制数字可能得到一个十二进制数字;在文字部分,DBMS知道没有溢出。但仍然不确定DBMS为什么会在意——它是否应该返回两个六位小数的结果,最多返回一个18位小数?

因为您在第一个示例中声明了变量,结果应该是相同的声明(即数字(18,6)),但事实并非如此


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

我上次尝试使用Sybase时遇到了相同的问题(很多年前)。出于SQL Server的心态,我没有意识到Sybase会试图强制输出小数——从数学上讲,这是它应该做的事情

从:

发生算术溢出错误时 新类型的小数点太少 用于容纳结果的位置

再往下看:

在隐式转换为数字的过程中 或十进制类型,比例损失 生成缩放误差。使用 arithabort数值_截断选项 确定这种错误的严重程度 被考虑在内。默认设置, arithabort数值_截断, 中止导致错误的语句 错误,但继续处理其他错误 交易中的报表或 一批。如果你设置了arithabort 数字截断关闭,自适应 服务器截断查询结果并 继续处理

因此,假设在您的场景中精度损失是可以接受的,您可能希望在事务开始时执行以下操作:

SET ARITHABORT NUMERIC_TRUNCATION OFF
SET ARITHABORT NUMERIC_TRUNCATION ON
然后在交易结束时:

SET ARITHABORT NUMERIC_TRUNCATION OFF
SET ARITHABORT NUMERIC_TRUNCATION ON

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

不直接相关,但使用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”列(或间接声明为decimal(4,3))。因此,您必须间接地将temp表列按比例和精度声明为所需的格式,就像我的例子中的000.000一样

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

希望这能节省一些时间:)

我不知道这是否增加了什么,但select(@a*@b)/@c在代数上是相同的,它会发生什么情况。