SQL Serverで興味深い問題が発生しました。次の再現例を検討してください。
CREATE TABLE #test (s_guid uniqueidentifier PRIMARY KEY);
INSERT INTO #test (s_guid) VALUES ('7E28EFF8-A80A-45E4-BFE0-C13989D69618');
SELECT s_guid FROM #test
WHERE s_guid = '7E28EFF8-A80A-45E4-BFE0-C13989D69618'
AND s_guid <> NEWID();
DROP TABLE #test;
s_guid <> NEWID()
条件が完全に役に立たないように見えることをしばらく忘れてください-これは単なる最小の再現例です。NEWID()
特定の定数値と一致する確率は非常に小さいため、毎回TRUEと評価される必要があります。
しかし、そうではありません。このクエリを実行すると、通常 1行が返されますが、時々(非常に頻繁に、10回のうち1回以上)0行が返されます。私のシステムでSQL Server 2008を使用して複製しました。上記のリンク(SQL Server 2014)を使用してオンラインで複製できます。
実行プランを見ると、クエリアナライザーは明らかに条件をs_guid < NEWID() OR s_guid > NEWID()
次のように分割していることがわかります。
...これが失敗する理由を完全に説明します(最初に生成されたIDが小さく、2番目のIDが指定されたIDよりも大きい場合)。
式の1つが非決定的であっても、SQL ServerはA <> B
として評価できA < B OR A > B
ますか?はいの場合、どこに文書化されていますか?それともバグを見つけましたか?
興味深いことに、AND NOT (s_guid = NEWID())
同じ実行計画(および同じランダムな結果)が得られます。
開発者がオプションで特定の行を除外して使用したいときにこの問題を発見しました:
s_guid <> ISNULL(@someParameter, NEWID())
以下の「ショートカット」として:
(@someParameter IS NULL OR s_guid <> @someParameter)
ドキュメントやバグの確認を探しています。コードはそれほど適切ではないため、回避策は不要です。