SQL ABS()在应用于可整除数据时返回意外的十进制数
在可除数据上应用abs时,整数商被转换为十进制SQL ABS()在应用于可整除数据时返回意外的十进制数,sql,Sql,在可除数据上应用abs时,整数商被转换为十进制 create table #data ( ConditionValue money, ConditionRateNbr real) insert into #data values(9665.77,37.61) select abs(conditionvalue/conditionrateNbr) Using_Abs ,* from #data --Using_Abs
create table #data ( ConditionValue money, ConditionRateNbr real)
insert into #data values(9665.77,37.61)
select abs(conditionvalue/conditionrateNbr) Using_Abs ,*
from #data
--Using_Abs ConditionValue ConditionRateNbr
--256.999969482422 9665.77 37.61
为什么会发生这种情况以及如何解决?这与“真实”数据类型是“近似数”有关,请参阅。我对SQL的了解不够深入,无法给出详细的解释,但我确实有一个解决方案,使用十进制数据类型I/o real:
create table #data ( ConditionValue money, ConditionRateNbr decimal(38,20))
insert into #data values(9665.77,37.61)
select abs(conditionvalue/conditionrateNbr) Using_Abs ,*
from #data
在我看来,使用十进制通常比使用实数更明智,以避免此类问题。假设使用sql server,但如果运行以下脚本:
CREATE TABLE #data
(
ConditionValue MONEY
, ConditionRateNbr REAL
)
INSERT INTO #data
VALUES ( 9665.77, 37.61 )
SELECT *
INTO data
FROM (
SELECT ABS(ConditionValue / ConditionRateNbr) Using_Abs
, conditionValue / ConditionRateNbr test
, *
FROM #data
)a
SELECT * FROM INFORMATION_SCHEMA.COLUMNS AS C WHERE C.TABLE_NAME = 'data'
DROP TABLE #data
DROP TABLE data
您将看到除法的结果是一个实数
。ABS(数值表达式)
函数显然,ABS
函数返回默认的float
float(53)
包含15位数字,因此返回15位数字
因此,返回的数据类型并不像您最初认为的那样是一个十进制
,而是另一个浮点
,默认为其最大大小(可以这么说)
如果您将字段定义为小数,请查看可能得到的结果。我所看到的使用货币比使用小数更可靠。 这里是另一个例子 我不知道到底为什么十进制数把3/1.5看成1.5
declare @real real = 1.5, @realup money=3
select @realUp numerator, @real denominator, @realup /cast (@real as money) money, @realup /cast(@real as decimal) decimal
--numerator denominator money decimal
--3.00 1.5 2.00 1.50000000000000000000000
你的数据库是什么?是否需要是真实的?我怀疑您可能使用了一个
十进制
,然后您的除法将得到您期望的整数值。使用二进制浮点类型时,舍入和表示问题。如果使用4字节类型(如REAL),情况会更糟,但DOUBLE也会这样做。此计算在SQLFIddle.com上的MySQL 5.5、5.6和SQLite中运行正常,但在PostgreSQL和SQL Server中返回时髦的结果。(甲骨文目前不工作,但根据我与甲骨文的经验,我会说它会按预期工作)。永远不要对货币量使用二进制浮点值(实数和双精度数据类型)。使用十进制、数字(在Oracle上)或货币(如果可用)。祝你好运。你没有为十进制值指定小数位数,所以它基本上被视为整数。这意味着在除法之前它被四舍五入到2,3.0/2是1.5。