sql-server - 如何防止存储过程中出现被零除错误?

标签 sql-server tsql stored-procedures division date-math

我试图执行 my brand-spanking-new 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,

为了完整披露/上下文,这里是整个 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)

我应该怎么做才能确保这里没有出现被零分隔的情况?

最佳答案

你可以使用 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

LiveDemo

关于sql-server - 如何防止存储过程中出现被零除错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34774030/

相关文章:

c# - C# 代码的单元测试,其中主要处理发生在 SQL 存储过程中

sql-server - 通过存储过程传递 "in"列表

sql-server - SQL : Is it possible to SUM() fields of INTERVAL type?

ruby - 安装 tiny_tds 在 mac os 10.10.5 上出现错误

tsql - T-SQL外键检查约束

SQL Server 如果不存在则插入

sql-server-2005 - 从动态 INSERT 获取 IDENTITY

sql-server - 如何使用 SQL 对行重新排序(不交换)

mysql - 在存储过程中遍历表的所有行时出现语法错误

php - 只允许在数据库中输入某些字符