4

クエリテキストの更新を間違えたときに、予測できないクエリ結果を見つけました。これが更新のためのクエリテキストです。

DECLARE @T TABLE (Id int,[Name] nvarchar(100),RNA int)

INSERT INTO @T(Id,[Name])
SELECT [Id],[Name] 
FROM (VALUES (1,N'D'),
             (2,N'B'),
             (3,N'S'),
             (4,N'A'),
             (5,N'F')
     ) AS vtable([Id],[Name])

UPDATE @T
SET RNA = T.RN
FROM (
  select PP.Name,ROW_NUMBER() OVER(ORDER BY PP.Name) RN,PP.RNA from @T PP
) T

select * from @T

私はどこで間違いがあったか知っています:

UPDATE @T

する必要があります

UPDATE T

しかし、なぜ結果(「悪い」クエリを含む)は次のようになります:

Id   Name  RNA
---- ----- -------
1    D     1
2    B     5
3    S     1
4    A     5
5    F     1

1と5の値はMIN(Id)とMAX(Id)だと思います。実行計画は次のようになります。

このような間違いがあるすべての状況で、この状況は同じでしょうか?

はいの場合、この動作は実用的な価値がありますか?

4

1 に答える 1

2

あらゆる種類の間違いで状況が同じになるわけではありません。非決定的な更新ステートメントがあります。つまり、理論的にRNは、サブクエリTのの任意の値をの任意の値に適用できます@T。基本的UPDATEに、このバージョンを実行しています。

SELECT  *
FROM    @t a
        CROSS JOIN
        (   SELECT  TOP 1
                    PP.Name,
                    ROW_NUMBER() OVER(ORDER BY PP.Name) RN,
                    PP.RNA 
            FROM    @T PP
            ORDER BY NEWID()
        ) T
OPTION (FORCE ORDER);

オンラインマニュアルには次のように記載されています。

UPDATEステートメントにFROM句が含まれている場合、更新される列の出現ごとに1つの値しか使用できないように指定されていない場合、つまりUPDATEステートメントが決定論的でない場合、UPDATEステートメントの結果は未定義です。

少し興味深いのは、上記を実行すると毎回異なる結果が得られることです(1/25の確率で同じ結果が2回続けて得られることを除けば)、を使用してランダムな並べ替えを削除するNEWID()と、同じ値が得られますRN各行の。ただし、更新は2つの異なるsを使用して、一貫して同じ結果を返しますRN。データに変更がなく、ランダムな要素が導入されていないため、結果がランダムな順序なしで一貫していることに驚いていません。オプティマイザーは、何度実行しても同じ実行プランを考え出すと思います。

更新クエリで明示的な順序が指定されていないため、順序はリーフ上のレコードの順序によるものです。レコードの順序が変更されると、結果が変更されます。これは、のレコード@Tを異なるIDの新しいテーブルに挿入することで表示できます

DECLARE @T2 TABLE (Id int,[Name] nvarchar(100),RNA int);
INSERT @T2 
SELECT  id, Name, NULL
FROM    @T
ORDER BY ROW_NUMBER() OVER(ORDER BY  NEWID())
OPTION (FORCE ORDER);

UPDATE @T2
SET RNA = T.RN
FROM (
  select PP.Name,ROW_NUMBER() OVER(ORDER BY PP.Name) RN,PP.RNA from @T2 PP
) T

SELECT  *
FROM    @T2;

これが常に最小値または最大値である理由はわかりませんが、RNこれを見つけるにはオプティマイザーを深く掘り下げる必要があると思います。これはおそらく、dbaスタック交換により適した新しい質問です。

于 2013-01-29T09:19:18.707 に答える