如何防止存储过程中出现被零除错误?
How can I prevent divide-by-zero errors in a Stored Procedure?
我试图从服务器资源管理器执行 ,我得到:
消息 8134,级别 16,状态 1,程序 duckbilledPlatypi,第 13 行
除以零时遇到错误。
这里是牵连的行 (13):
@Week1End Week1End,
...在更多上下文中:
DECLARE
@Week1End datetime,
@Week2begin datetime
Select Ind.Description,
@BegDate BegDate,
@Week1End Week1End,
@Week1End Week2Begin,
@EndDate EndDate,
对于完整 disclosure/context,这是整个 SP,因为它现在存在:
CREATE PROCEDURE [dbo].[duckbilledPlatypi]
@Unit varchar(25),
@BegDate datetime,
@EndDate datetime
AS
DECLARE
@Week1End datetime,
@Week2begin datetime
Select Ind.Description,
@BegDate BegDate,
@Week1End Week1End,
@Week1End Week2Begin,
@EndDate EndDate,
SUM(CASE WHEN Ind.InvoiceDate BETWEEN @BegDate AND @Week1End THEN Ind.QtyShipped ELSE 0 END)
Week1Usage,
SUM(CASE WHEN Ind.InvoiceDate BETWEEN @Week2Begin AND @EndDate THEN Ind.QtyShipped ELSE 0 END)
Week2Usage,
SUM(CASE WHEN Ind.InvoiceDate BETWEEN @BegDate AND @Week1End THEN Ind.Price ELSE 0 END)
Week1Price,
SUM(CASE WHEN Ind.InvoiceDate BETWEEN @Week2Begin AND @EndDate THEN Ind.Price ELSE 0 END) -
SUM(CASE WHEN Ind.InvoiceDate BETWEEN @BegDate AND @Week1End THEN Ind.QtyShipped ELSE 0 END)
UsageVariance,
SUM(CASE WHEN Ind.InvoiceDate BETWEEN @Week2Begin AND @EndDate THEN Ind.QtyShipped ELSE 0 END) -
SUM(CASE WHEN Ind.InvoiceDate BETWEEN @BegDate AND @Week1End THEN Ind.Price ELSE 0 END)
PriceVariance,
(SUM(CASE WHEN Ind.InvoiceDate BETWEEN @Week2Begin AND @EndDate THEN Ind.QtyShipped ELSE 0
END) -
SUM(CASE WHEN Ind.InvoiceDate BETWEEN @BegDate AND @Week1End THEN Ind.Price ELSE 0 END) )
/ SUM(CASE WHEN Ind.InvoiceDate BETWEEN @BegDate AND @Week1End THEN Ind.Price ELSE 0 END)
PercentageOfPriceVariance
From InvoiceDetail Ind
Where Ind.Unit = @Unit
AND Ind.InvoiceDate BETWEEN @BegDate AND @EndDate
Group By Ind.Description
我的猜测是 @Week1End Week1End 失败了,因为它没有被赋予一个值,因此它是空的。我不知道我是否应该做这样的事情来防止 0s/nulls:
DECLARE
@Week1End datetime = BegDate + 6;
@Week2begin datetime = BegDate + 7;
...或类似这样的内容:
Select Ind.Description,
@BegDate BegDate,
@Week1End BegDate+6,
@Week2Begin BegDate+7,
@EndDate EndDate,
...或者完全是其他东西。
您可能会说,我不知道日期数学实际上应该如何完成。真正需要的日期是:
Week1Begin is the "BegDate" the user provided as a parameter
Week1End needs to be six days after Week1Begin
Week2Begin needs to be seven days after Week1Begin
Week2End is the "EndDate" the user provided as a parameter
例如,如果用户为 BegDate 输入“12/27/2015”,为 EndDate 输入“1/6/2016”,则这些值需要为:
Week1Begin = 12/27/2015
Week1End = 1/2/2016
Week2Begin = 1/3/2016
Week2End = 1/6/2016 (week2 is only a four-day week in this case, due to what the user entered)
我应该怎么做才能确保这里没有 div by zeros 出现?
你可以使用 NULLIF
:
(SUM(CASE WHEN Ind.InvoiceDate BETWEEN @Week2Begin AND @EndDate THEN Ind.QtyShipped ELSE 0
END) -
SUM(CASE WHEN Ind.InvoiceDate BETWEEN @BegDate AND @Week1End THEN Ind.Price ELSE 0 END) )
/ NULLIF(SUM(CASE WHEN Ind.InvoiceDate BETWEEN @BegDate AND @Week1End THEN Ind.Price ELSE 0 END),0)
PercentageOfPriceVariance
因此,当除数为 0
时,最终结果将为 NULL
。如果您需要为这种情况提供特殊价值,请添加 COALESCE
:
COALESCE(exp1 / NULLIF(exp2, 0), special_value) AS result
我试图从服务器资源管理器执行
消息 8134,级别 16,状态 1,程序 duckbilledPlatypi,第 13 行 除以零时遇到错误。
这里是牵连的行 (13):
@Week1End Week1End,
...在更多上下文中:
DECLARE
@Week1End datetime,
@Week2begin datetime
Select Ind.Description,
@BegDate BegDate,
@Week1End Week1End,
@Week1End Week2Begin,
@EndDate EndDate,
对于完整 disclosure/context,这是整个 SP,因为它现在存在:
CREATE PROCEDURE [dbo].[duckbilledPlatypi]
@Unit varchar(25),
@BegDate datetime,
@EndDate datetime
AS
DECLARE
@Week1End datetime,
@Week2begin datetime
Select Ind.Description,
@BegDate BegDate,
@Week1End Week1End,
@Week1End Week2Begin,
@EndDate EndDate,
SUM(CASE WHEN Ind.InvoiceDate BETWEEN @BegDate AND @Week1End THEN Ind.QtyShipped ELSE 0 END)
Week1Usage,
SUM(CASE WHEN Ind.InvoiceDate BETWEEN @Week2Begin AND @EndDate THEN Ind.QtyShipped ELSE 0 END)
Week2Usage,
SUM(CASE WHEN Ind.InvoiceDate BETWEEN @BegDate AND @Week1End THEN Ind.Price ELSE 0 END)
Week1Price,
SUM(CASE WHEN Ind.InvoiceDate BETWEEN @Week2Begin AND @EndDate THEN Ind.Price ELSE 0 END) -
SUM(CASE WHEN Ind.InvoiceDate BETWEEN @BegDate AND @Week1End THEN Ind.QtyShipped ELSE 0 END)
UsageVariance,
SUM(CASE WHEN Ind.InvoiceDate BETWEEN @Week2Begin AND @EndDate THEN Ind.QtyShipped ELSE 0 END) -
SUM(CASE WHEN Ind.InvoiceDate BETWEEN @BegDate AND @Week1End THEN Ind.Price ELSE 0 END)
PriceVariance,
(SUM(CASE WHEN Ind.InvoiceDate BETWEEN @Week2Begin AND @EndDate THEN Ind.QtyShipped ELSE 0
END) -
SUM(CASE WHEN Ind.InvoiceDate BETWEEN @BegDate AND @Week1End THEN Ind.Price ELSE 0 END) )
/ SUM(CASE WHEN Ind.InvoiceDate BETWEEN @BegDate AND @Week1End THEN Ind.Price ELSE 0 END)
PercentageOfPriceVariance
From InvoiceDetail Ind
Where Ind.Unit = @Unit
AND Ind.InvoiceDate BETWEEN @BegDate AND @EndDate
Group By Ind.Description
我的猜测是 @Week1End Week1End 失败了,因为它没有被赋予一个值,因此它是空的。我不知道我是否应该做这样的事情来防止 0s/nulls:
DECLARE
@Week1End datetime = BegDate + 6;
@Week2begin datetime = BegDate + 7;
...或类似这样的内容:
Select Ind.Description,
@BegDate BegDate,
@Week1End BegDate+6,
@Week2Begin BegDate+7,
@EndDate EndDate,
...或者完全是其他东西。
您可能会说,我不知道日期数学实际上应该如何完成。真正需要的日期是:
Week1Begin is the "BegDate" the user provided as a parameter
Week1End needs to be six days after Week1Begin
Week2Begin needs to be seven days after Week1Begin
Week2End is the "EndDate" the user provided as a parameter
例如,如果用户为 BegDate 输入“12/27/2015”,为 EndDate 输入“1/6/2016”,则这些值需要为:
Week1Begin = 12/27/2015
Week1End = 1/2/2016
Week2Begin = 1/3/2016
Week2End = 1/6/2016 (week2 is only a four-day week in this case, due to what the user entered)
我应该怎么做才能确保这里没有 div by zeros 出现?
你可以使用 NULLIF
:
(SUM(CASE WHEN Ind.InvoiceDate BETWEEN @Week2Begin AND @EndDate THEN Ind.QtyShipped ELSE 0
END) -
SUM(CASE WHEN Ind.InvoiceDate BETWEEN @BegDate AND @Week1End THEN Ind.Price ELSE 0 END) )
/ NULLIF(SUM(CASE WHEN Ind.InvoiceDate BETWEEN @BegDate AND @Week1End THEN Ind.Price ELSE 0 END),0)
PercentageOfPriceVariance
因此,当除数为 0
时,最终结果将为 NULL
。如果您需要为这种情况提供特殊价值,请添加 COALESCE
:
COALESCE(exp1 / NULLIF(exp2, 0), special_value) AS result