7

そこで、今日、SQL Server の奇妙な動作を発見しました。

このようなテーブルがあるとします。id は主キーです

╔════╦══════╦════════╗
║ id ║ name ║ active ║
╠════╬══════╬════════╣
║  1 ║ a    ║      0 ║
║  2 ║ a    ║      1 ║
╚════╩══════╩════════╝

そして、私が持っているとしfiltered unique index on name where active = 1ます。今、行のアクティブに切り替え、最初の行を非アクティブに設定し、2番目の行をアクティブに設定したいだけです。次のように更新しようとすると

update Table1 set 
    active = n.active
from Table1 as t
inner join (values (1, 1), (2, 0)) as n(id, active) on n.id = t.id

それは正常に動作します。しかし、マージしようとすると:

merge Table1 as t
using (values (1, 1), (2, 0)) as n(id, active) on n.id = t.id
when matched then
    update set active = n.active;

エラーで失敗した場合Cannot insert duplicate key row in object 'dbo.Table1' with unique index 'ix_Table1'. The duplicate key value is (a)

さらに奇妙なことに、このようなテーブルがある場合 (最初の行がアクティブ = 1 で、2 行目がアクティブ = 0 の場合):

╔════╦══════╦════════╗
║ id ║ name ║ active ║
╠════╬══════╬════════╣
║  1 ║ a    ║      1 ║
║  2 ║ a    ║      0 ║
╚════╩══════╩════════╝

次のようにマージします。

merge Table1 as t
using (values (1, 0), (2, 1)) as n(id, active) on n.id = t.id
when matched then
    update set active = n.active;

それは再び正常に動作します。したがって、マージは行ごとに更新し、各行の後にインデックスをチェックしているように見えます。一意の制約、フィルターなしの一意のインデックスを確認しましたが、すべて正常に機能します。マージとフィルター処理されたインデックスを組み合わせた場合にのみ失敗します。

質問は、これはバグですか? もしそうなら、これに対する最善の回避策は何ですか?

sql fiddle demoで試すことができます。

4

1 に答える 1