SQL Serverの - ゼロによる除算ストレンジ
-
22-08-2019 - |
質問
私は、次のクエリを実行しています:
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の重要な部分(すべてのparamsは、float型のものである):
set @m = (@p2Y - @p1Y)/(@p2X - @p1X)
set @b = @p1Y - (@m*@p1X)
set @result = (@m*@xval+@b)
ビューvPolygonSegmentsはP1X = P2X(これらのレコードを除く)は、レコードが含まれていません。私は私のクエリを実行すると、まだ、SQL Serverはエラーを返します:「ゼロ除算エラーが発生しました。」不思議なことに、私は(where句なし)のみ最初の2行を実行する場合、クエリが返す結果をうまく。
どのように私はこの問題を解決するか、および/または何がこの動作を引き起こしている?
の編集を ここに私のビューがあります:
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
解決
ここでの問題は、WHERE句内の関数が評価される前に選択原因で機能が評価されていることです。この状態は非常にまれですが、それは可能ですので、あなたはそれに対してコーディングする必要があります。私はそれが安全にゼロ事情により除算を処理できるように、機能を変更することを示唆しています。この行を変更します:
set @m = (@p2Y - @p1Y)/(@p2X - @p1X)
この宛先:
set @m = (@p2Y - @p1Y)/NullIf((@p2X - @p1X), 0)
とき@ P2X - P1X = 0、@、NULLIF関数はNULLを返します。その後、@mがします他のすべての値として、nullになります。ほとんどの場合、この関数はNULLを返します。
あなたのWHERE句で、あなたが持っている...
Where dbo.fn_Yval(p1X, p1Y, p2X, p2Y, 4.003318) > 0
関数がNULLを返した場合、それは0に比較しないであろうと、とにかく除外なってしまいます。
他のヒント
、それはおそらく問題です。問合せは、下記の問題を回避する必要がありますが、問題が最良のあなたの関数自体の内部に固定されます:
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
私はそれがビューがクエリのマテリアライズされてどのように関係している疑いがあります。オプティマイザはP1.decX <> P2.decX
前のソースデータにこのフィルタを適用することを選択するかもしれないようでは、の本質的の句は、ビューのソースクエリに追加する場所にその機能を追加します。
とにかく、あなたは知りません。フロントアップ不良データを処理する方法のための計画を持っているベスト。 NullIf
の提案この場合は良いもののように思える。
問題が発生したときに、P2X = @ P1X @。あなたは何をそのような場合に起こることを期待していますか?
私は、これはどのような方法で質問に答えるだろうことを知りませんが、レコードごとに二回fn_Yvalを評価しています。なぜビュー内の列関数の結果を作ってみませんか?次に、あなたのwhere句は、 "どこyvalを指定> 0" のようなものになる可能性があります。
編集:好奇心から、fn_Yvalは、任意の副作用を持っていない、それは
のでしょうか?私はそれが加入またはビューが関与しているwhere句を使用して、ゼロエラーによって除算を引き起こす可能性がデータを削除しようとする問題に見つかりました。どちらのJOIN句でデータをフィルタリングしたり、関数内でそれをフィルタリングします。
更新:理由のちょうど種類の「G Mastrosは」書きました。