0

我正在执行以下查询:

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 的重要部分(所有参数都是浮点类型):

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
4

6 回答 6

3

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

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

对此:

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

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

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

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

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

于 2008-12-17T18:13:21.727 回答
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
于 2008-12-17T17:51:43.253 回答
2

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

无论如何,您不知道何时要在没有相同约束的其他地方重用该功能。最好预先制定如何处理不良数据的计划。在这种情况下,这些NullIf建议似乎是一个很好的建议。

于 2008-12-17T18:19:47.313 回答
1

当@p2X = @p1X 时会出现问题。在这种情况下,您预计会发生什么?

于 2008-12-17T17:45:49.753 回答
0

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

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

于 2008-12-17T17:57:26.033 回答
0

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

更新:出于“G Mastros”所写的那种原因。

于 2008-12-17T18:13:21.523 回答