4

我认为最好以简单示例的形式提出这个问题。以下 SQL 块导致“DB-Library Error:20049 Severity:4 Message:Data-conversion 导致溢出”消息,但这是怎么回事?

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

4 回答 4

4

上次尝试使用 Sybase 时(多年前)我遇到了同样的问题。从 SQL Server 的思维方式出发,我没有意识到 Sybase 会尝试强制输出小数——从数学上讲,这是它应该做的。:)

Sybase 手册

当新类型的小数位数太少而无法容纳结果时,就会发生算术溢出错误。

再往下:

在隐式转换为数字或小数类型期间,比例丢失会产生比例错误。使用 arithabort numeric_truncation 选项来确定此类错误的严重程度。默认设置 arithabort numeric_truncation on 会中止导致错误的语句,但会继续处理事务或批处理中的其他语句。如果将 arithabort numeric_truncation 设置为 off, Adaptive Server 将截断查询结果并继续处理。

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

SET ARITHABORT NUMERIC_TRUNCATION OFF

然后在您的交易结束时:

SET ARITHABORT NUMERIC_TRUNCATION ON

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

于 2008-10-05T11:58:26.583 回答
1

这只是推测,但可能是 DBMS 不查看变量的动态值而只查看潜在值?因此,一个六进制数字除以一个六进制数字可以得到一个十二进制数字;在字面除法中,DBMS 知道没有溢出。不过,仍然不确定为什么 DBMS 会关心——它不应该将两个 6 位小数除法的结果返回为 18 位小数吗?

于 2008-10-03T19:29:17.047 回答
1

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

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

于 2008-10-04T23:11:27.333 回答
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”列(或间接声明为 decimal(4,3) )。因此,您必须将临时表列的比例和精度间接声明为您想要的格式,在我的例子中是 000.000。

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

希望这可以节省一些时间:)

于 2015-09-23T11:39:25.143 回答