2013-10-22 8 views
6

今日、私は奇妙な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 

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

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; 

:しかし、私は、マージを行うにしよう。

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

このようにそれをマージ:私はこのようなテーブルを持っている場合

ても見知らぬ人(最初の行を= 1と第2の行は、アクティブアクティブ= 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; 

それをはうまく機能します再度。だから、実際にはmergeは更新行ごとにと各行の後にindexeをチェックするように見えます。私はユニークな制約、フィルタなしのユニークなインデックスを確認しました。マージとフィルタリングされたインデックスを組み合わせると失敗します。

これはバグですか、そうであれば、これにはどのような回避策がありますか?

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

答えて

1

私はsqlblog.comこの記事見つけた - MERGE Bug with Filtered Indexesを、それはPaul Whiteによって書かれ、日付2012年

彼は、回避策のカップル与えた:で参照されるすべての列を追加する

  • をフィルタリングされたインデックスのWHERE句をインデックスキーに追加します(INCLUDEは十分ではありません)。または
  • トレースフラグ8790でクエリを実行します。 OPTION(QUERYTRACEON 8790)。研究のビットの後

私は、更新に主キー列を追加する場合、クエリになるので、それは、[OK]を動作することを発見しました:

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, id = n.id; 

私はそれをすることも可能だと思います更新されたインデックスから列を追加しますが、まだテストしていません。

sql fiddle demo

関連する問題