我有这个错误信息:

Msg 8134,级别16,状态1,第1行,除以零错误。

写SQL代码的最好方法是什么,这样我就再也不会看到这个错误消息了?

我可以做以下任何一件事:

添加where子句,使除数永远不为零

Or

我可以添加一个case语句,这样就可以对0进行特殊处理。

使用NULLIF子句是最好的方法吗?

有没有更好的办法,或者如何实施?


当前回答

我写了一个函数来处理我的存储过程:

print 'Creating safeDivide Stored Proc ...'
go

if exists (select * from dbo.sysobjects where  name = 'safeDivide') drop function safeDivide;
go

create function dbo.safeDivide( @Numerator decimal(38,19), @divisor decimal(39,19))
   returns decimal(38,19)
begin
 -- **************************************************************************
 --  Procedure: safeDivide()
 --     Author: Ron Savage, Central, ex: 1282
 --       Date: 06/22/2004
 --
 --  Description:
 --  This function divides the first argument by the second argument after
 --  checking for NULL or 0 divisors to avoid "divide by zero" errors.
 -- Change History:
 --
 -- Date        Init. Description
 -- 05/14/2009  RS    Updated to handle really freaking big numbers, just in
 --                   case. :-)
 -- 05/14/2009  RS    Updated to handle negative divisors.
 -- **************************************************************************
   declare @p_product    decimal(38,19);

   select @p_product = null;

   if ( @divisor is not null and @divisor <> 0 and @Numerator is not null )
      select @p_product = @Numerator / @divisor;

   return(@p_product)
end
go

其他回答

为了避免“除零”错误,我们编写了这样的程序:

Select Case when divisor=0 then null
Else dividend / divisor
End ,,,

但这里有一种更好的方式:

Select dividend / NULLIF(divisor, 0) ...

现在唯一的问题是记住NullIf位,如果我使用“/”键。

当错误传播回调用程序时,可以适当地处理它(如果需要,可以忽略它)。在c#中,SQL中发生的任何错误都会抛出一个异常,我可以捕获并在我的代码中处理,就像任何其他错误一样。

I agree with Beska in that you do not want to hide the error. You may not be dealing with a nuclear reactor but hiding errors in general is bad programming practice. This is one of the reasons most modern programming languages implement structured exception handling to decouple the actual return value with an error / status code. This is especially true when you are doing math. The biggest problem is that you cannot distinguish between a correctly computed 0 being returned or a 0 as the result of an error. Instead any value returned is the computed value and if anything goes wrong an exception is thrown. This will of course differ depending on how you are accessing the database and what language you are using but you should always be able to get an error message that you can deal with.

try
{
    Database.ComputePercentage();
}
catch (SqlException e)
{
    // now you can handle the exception or at least log that the exception was thrown if you choose not to handle it
    // Exception Details: System.Data.SqlClient.SqlException: Divide by zero error encountered.
}

我是这样解决的:

IIF(ValueA != 0, Total / ValueA, 0)

它可以被包装在一个更新中:

SET Pct = IIF(ValueA != 0, Total / ValueA, 0)

或者在选择中:

SELECT IIF(ValueA != 0, Total / ValueA, 0) AS Pct FROM Tablename;

想法吗?

在这种情况下,你可以除以0。商业规则是计算库存周转,你用一段时间内的销售成本,按年计算。在你得到年化数字之后,你要除以该时期的平均库存。

I'm looking at calculating the number of inventory turns that occur in a three month period. I have calculated that I have Cost of Goods sold during the three month period of $1,000. The annual rate of sales is $4,000 ($1,000/3)*12. The beginning inventory is 0. The ending inventory is 0. My average inventory is now 0. I have sales of $4000 per year, and no inventory. This yields an infinite number of turns. This means that all my inventory is being converted and purchased by customers.

这是关于如何计算库存周转的业务规则。

使用NULLIF(exp,0),但以这种方式- NULLIF(ISNULL(exp,0),0)

如果exp为空,NULLIF(exp,0)将中断,但NULLIF(ISNULL(exp,0),0)将不会中断