SQL Server - 奇怪的划分为零

时间:2008-12-17 17:42:00

标签: sql-server divide-by-zero

我正在执行以下查询:

Select guiPolygonID, dbo.fn_Yval(p1X, p1Y, p2X, p2Y, 4.003318)
From [vPolygonSegments]
Where dbo.fn_Yval(p1X, p1Y, p2X, p2Y, 4.003318) > 0

函数fn_Yval的重要部分(所有参数都是float类型):

set @m = (@p2Y - @p1Y)/(@p2X - @p1X)
set @b = @p1Y - (@m*@p1X)
set @result = (@m*@xval+@b)

视图vPolygonSegments不包含p1X = p2X的记录(不包括那些记录)。但是,当我执行查询时,SQL Server会返回错误:“遇到零除错误”。奇怪的是,如果我只执行前两行(没有where子句),查询返回结果就好了。

如何解决此问题,和/或导致此行为的原因是什么?

修改 以下是我的观点:

Select P1.guiPolygonID,
    P1.decX as p1X, P1.decY as p1Y,
    P2.decX as p2X, P2.decY as p2Y
From PolygonPoints P1, PolygonPoints P2
Where P1.guiPolygonID = P2.guiPolygonID
    and (
        P1.lPointNumber - P2.lPointNumber = 1
        or (
            -- Some other unimportant code
        )
    )
    and P1.decX <> P2.decX

6 个答案:

答案 0 :(得分:3)

这里的问题是在评估where子句中的函数之前评估select原因中的函数。这种情况非常罕见,但它是可能的,因此您需要对其进行编码。我建议您修改该功能,以便它可以安全地处理除零情况。改变这一行:

set @m = (@p2Y - @p1Y)/(@p2X - @p1X)

对此:

set @m = (@p2Y - @p1Y)/NullIf((@p2X - @p1X), 0)

当@ p2x - @ p1x = 0时,NULLIF函数将返回NULL。随后,@ m将为null,所有其他值也将为null。最有可能的是,该函数将返回NULL。

在你的where子句中,你有......

Where dbo.fn_Yval(p1X, p1Y, p2X, p2Y, 4.003318) > 0

当函数返回NULL时,它不会与0进行比较,最终会被过滤掉。

答案 1 :(得分:2)

正如Joel Coehoorn指出的那样,这是可能的问题。下面的查询应该避免这个问题,但问题最好在函数本身内修复:

Select guiPolygonID, dbo.fn_Yval(p1X, p1Y, p2X, p2Y, 4.003318)
From [vPolygonSegments]
Where p2X <> p1X and dbo.fn_Yval(p1X, p1Y, p2X, p2Y, 4.003318) > 0

答案 2 :(得分:2)

我怀疑它与如何为查询实现视图有关。将该函数添加到where子句本质上将其添加到视图的源查询中,以便优化器可以选择在P1.decX <> P2.decX之前将此过滤器应用于源数据。

无论如何,你不知道什么时候你想要在没有相同约束的其他地方重用那个函数。最好有一个如何预先处理坏数据的计划。在这种情况下,NullIf建议似乎很好。

答案 3 :(得分:1)

@ p2X = @ p1X时出现问题。在那种情况下你期望发生什么?

答案 4 :(得分:0)

我不知道这会以任何方式回答这个问题,但你会为每条记录评估fn_Yval两次。为什么不在视图中将函数的结果作为列?然后,你的where子句可能是“yval&gt; 0”。

编辑:出于好奇,fn_Yval没有任何副作用,是吗?

答案 5 :(得分:0)

我发现在涉及连接或视图时尝试删除可能导致使用where子句的零错误的数据是有问题的。过滤join子句中的数据或在函数中过滤掉它。

更新:仅仅因为“G Mastros”写道的原因。