日期:2014-05-17  浏览次数:20337 次

存储过程中字段计算,传入的小数在计算前就被四舍五入的问题。
存储过程部分代码如下:
BasicUnit_1在数据库中为 money类型
我这里的@BasicUnit_1 是用来计算BasicUnit_1字段的倍率。
根据出厂价*倍率来批量设置 BasicUnit_1 的价格。
BasicUnit_1 = ROUND((FactoryPrice * @BasicUnit_1),2)
用了好些保留两位的方法,也测试了单纯的 FactoryPrice * @BasicUnit_1 计算
假设 FactoryPrice = 4 传入 @BasicUnit_1 = 1.2 时   BasicUnit_1结果为4
传入 @BasicUnit_1 = 1.5 时   BasicUnit_1结果为8
应该是@BasicUnit_1 在计算前就被进行了四舍五入。以前没遇到过这个问题,求解决。

另外我这里用到了临时表来暂存一个批量修改的ID列表。
这个条件会被执行到20来次的价格设置条件,为避免相同的条件查询就做了个临时表。

本来想用表变量,无奈不能用
EXEC来执行带表变量的SQL语句。

也想过用条件判断字符串拼接来做更新语句,代码实在有些长。这个功能很少用到。
不知道这样做性能如何。


ALTER procedure [dbo].[UpdatePrice]--更新产品价格
(
--价格信息
@RowCounts int=0 output,--返回受影响的行数
@FactoryPrice Money = 0,--出厂价格
@BasicUnit_1 Decimal = 0,
@BasicUnit_2 Decimal = 0,
@BasicUnit_3 Decimal = 0,
@BasicUnit_4 Decimal = 0,
@BasicUnit_5 Decimal = 0,
@BasicUnit_6 Decimal = 0,
@Unit2_1 Decimal = 0,--包装2价格
@Unit2_2 Decimal = 0,
@Unit2_3 Decimal = 0,
@Unit2_4 Decimal = 0,
@Unit2_5 Decimal = 0,
@Unit2_6 Decimal = 0,
@Unit3_1 Decimal = 0,--包装3价格
@Unit3_2 Decimal = 0,
@Unit3_3 Decimal = 0,
@Unit3_4 Decimal = 0,
@Unit3_5 Decimal = 0,
@Unit3_6 Decimal = 0,
@strWhere varchar(1000)
)

AS

SET NOCOUNT ON
SET ANSI_WARNINGS OFF
SET XACT_ABORT ON
DECLARE @Sql VARCHAR(1000)

CREATE TABLE #TempTable (ProductID INT)
SET @Sql = 'INSERT INTO #TempTable (ProductID) SELECT (ProductID) FROM V_Products WHERE '+ @strWhere
EXEC(@Sql)

BEGIN TRAN
SET @RowCounts = @@RowCount

if(@FactoryPrice != 0)
begin
UPDATE ProductPrice SET FactoryPrice=@FactoryPrice where ProductID IN (select ProductID from #TempTable)
SET @RowCounts = @RowCounts + @@RowCount
end
----------------包装单位1价格----------------------------
IF ISNULL(@BasicUnit_1, 0) != 0
BEGIN
UPDATE ProductPrice SET BasicUnit_1 = ROUND((FactoryPrice * @BasicUnit_1),2) where ProductID IN (select ProductID from #TempTable)
SET @RowCounts = @RowCounts + @@RowCount
END
COMMIT TRAN
PRINT(@RowCounts)

------最佳解决方案--------------------
根据我以前给银行做系统的经验,由于都是上千亿,并且最后汇总不能误差大于1块钱。所以当时公司规定,一般都保留到小数点6位,然后在最后一步汇总的时候才convert来截取小数位。这样误差会小很多。如果过早四舍五入,当数据量大的时候,误差就比较明显。
------其他解决方案--------------------
 @BasicUnit_1  --> 这个变量 你设什么类型? 试试 numeric(18,2)
------其他解决方案--------------------
declare @variant decimal(p,s)

decimal默认为decimal(18,0)
------其他解决方案--------------------
晕死,我在建表的时候是 (18,2)的 这里没想到~ 
------其他解决方案--------------------
引用:
根据我以前给银行做系统的经验,由于都是上千亿,并且最后汇总不能误差大于1块钱。所以当时公司规定,一般都保留到小数点6位,然后在最后一步汇总的时候才convert来截取小数位。这样误差会小很多。如果