SQL Server WHILE循环实现的拣货单总价计算函数返回0问题求助
问题根因
排查到4个核心错误:
- 变量未初始化:声明的
@fTotalCost没有设置初始值,SQL Server中未初始化的变量默认值为NULL,NULL + 任意数值结果还是NULL,最终赋值给整型返回值时会被转为0 - 参数拼写错误:循环内查询的WHERE条件中,你把参数
@psPickTicket拼写成了@psPickTcket(少了一个字母e),导致子查询永远匹配不到数据,返回的求和结果固定为0 - LEFT JOIN逻辑错误:你对
tblCase用了LEFT JOIN,但后面又加了C.CaseStatus的过滤条件,实际上会等价于INNER JOIN,如果某行拣货单没有符合状态的关联Case记录,该行的金额会被直接忽略 - 返回值类型错误:函数返回值定义为
TInteger整型,你计算的金额是带小数的浮点数,赋值给整型变量会直接丢失小数部分,就算计算正确也会出现精度损失
优化后代码(去掉无意义的循环,直接用单条聚合查询实现,性能更高)
Alter Function fn_CalculateAllocatedPTPrice (@psPickTicket TPickTicketNo) ------------------------------- Returns Decimal(18,2) -- 用高精度小数类型存金额,避免精度损失 As Begin Declare @fTotalCost Decimal(18,2) = 0; -- 初始化变量 SELECT @fTotalCost = ISNULL(SUM(P.RetailUnitPrice * P.UnitsOrdered), 0) FROM tblPickTicketDtl P -- 把Case状态的过滤提前到JOIN条件里,保留LEFT JOIN的语义 LEFT JOIN tblCase C ON P.PickTicketNo = C.PickTicketNo AND C.CaseStatus IN ('A','G','K','E','L','S') WHERE P.PickTicketNo = @psPickTicket; Return(@fTotalCost); End
如果你确实需要保留原来的循环写法,只要修正前面提到的3个错误即可:
- 给
@fTotalCost设置初始值0 - 修正参数拼写错误
- 调整LEFT JOIN的过滤条件位置
- 把返回值改为适合存金额的小数类型
内容的提问来源于stack exchange,提问作者NorSer
相关产品推荐
相关产品推荐

