此 SQL 代码是否容易出现舍入错误?
我发现了一些奇怪的行为,其中存储过程返回的结果不准确一两分钱。
这是代码(不是我写的):
ALTER PROCEDURE [dbo].[TN_GetSimpleBalance]
@custID int,
@nBalance decimal (8,2) output
AS
declare @ArBalance as decimal (8,2)
declare @custStatusCode varchar (2)
declare @unbilledCallsAmount as decimal (8,2)
set @nBalance = 0
set @ArBalance = 0
set @custstatusCode = ''
set @unbilledCallsAmount = 0
SET NOCOUNT ON
select @unbilledCallsAmount = isnull(sum(callcharge+taxamount),0)
from call with (NOLOCK) where custid = @custID and callstatuscode in ('R', 'B')
--get AR balance
select @ArBalance = isnull(sum(amount),0)
from artran with (NOLOCK)
where custid = @custID AND POSTEDFLAG ='Y'
set @nBalance = @unbilledCallsAmount + @ArBalance
@nBalance
显示为零,尽管另一个应用程序告诉我客户有 0.02 美元。 callcharge
和 taxamount
都是货币数据类型。
这是我第一次遇到这种情况,但我正在将一些相关代码移至生产环境,并被“要求”对此进行研究。
你怎么看?货币和十进制数据类型之间有什么奇怪的地方吗?您认为还有什么可以解释这一点吗?
I have discovered some strange behavior where a stored procedure is returning inaccurate results by a penny or two.
Here's the code (I didn't write it):
ALTER PROCEDURE [dbo].[TN_GetSimpleBalance]
@custID int,
@nBalance decimal (8,2) output
AS
declare @ArBalance as decimal (8,2)
declare @custStatusCode varchar (2)
declare @unbilledCallsAmount as decimal (8,2)
set @nBalance = 0
set @ArBalance = 0
set @custstatusCode = ''
set @unbilledCallsAmount = 0
SET NOCOUNT ON
select @unbilledCallsAmount = isnull(sum(callcharge+taxamount),0)
from call with (NOLOCK) where custid = @custID and callstatuscode in ('R', 'B')
--get AR balance
select @ArBalance = isnull(sum(amount),0)
from artran with (NOLOCK)
where custid = @custID AND POSTEDFLAG ='Y'
set @nBalance = @unbilledCallsAmount + @ArBalance
@nBalance
is showing zero, even though another app is telling me the customer has $.02. callcharge
and taxamount
are both money datatypes.
This is the first time I've encountered this condition, but I am moving some related code to production and have been "asked" to research this.
What's your take? Is there weirdness going between money and decimal datatypes? Anything else you think might explain this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我在您的代码中没有看到任何金钱数据类型,但我假设 call.callcharge & call.taxamount 是多少?我暂时不知道精度问题。
也许您能做的最好的事情就是尝试找到数据存在这种差异的特定测试用例,并看看是否可以一致地重现它。然后,您可以一次将逻辑分解为一个语句,并找出差异所在。
您是否有可能通话费或税额为空? (空+(-$0.02)) =>无效的;也许
应该是:
如果这些 select 语句不返回任何记录,@unbilledCallsAmount 或 @ArBalance 也可能为 null。
哈特哈,
I don't see any money datatypes in your code, but I assume call.callcharge & call.taxamount are? I don't know about the precision issue offhand.
Probably the best thing you can do is try to find a specific test case where data has this discrepancy, and see if you can reproduce it consistently. Then you can pick apart the logic a statement at a time and figure out where the discrepancy is introduced.
Is it possible you have a null callcharge or null taxamount? (null+(-$0.02)) => null; maybe
should be:
@unbilledCallsAmount or @ArBalance might also be null if those select statements return no records.
HTH,
callcharge
和taxamount
是什么数据类型?我会用该数据类型进行所有计算,并在最后转换为十进制。目前,所有中间变量都是小数,这意味着舍入误差会复合。直到最后不要绕圈。What data types are
callcharge
andtaxamount
? I would do all my calculations in that data type and cast to decimal at the end. Currently all your intermediate vars are decimals which means that rounding errors compound. Don't round until the end.当使用它时,并尝试不同的硬编码值作为值 callcharge &税额:
如果您的通话费用或税额中有 3 位或更多小数位,我只能得到不同的值。因此,如果您没有这样的数据,也没关系。
when using this, and trying different hard coded values for values callcharge & taxamount:
I could only get the values to differ if you have 3 or more decimal places in callcharge or taxamount. So if you don't have data like that you are ok.
由于 数据类型优先级。和金钱-> numeric (near end) 是四舍五入的,
所以 @unbilledCallsAmount 和 @ArBalance 都会四舍五入,并且都是累积的。
Your money (from comment) columns are being converted to decimal(8,2) because of datatype precedence. And money-> numeric (near end) is rounded they are rounded
So both @unbilledCallsAmount and @ArBalance will be rounded and it's all cumulative.