So habe ich heute ein seltsames SQL Server-Verhalten entdeckt.Merge mit Unique gefilterten Index
Angenommen, ich habe eine Tabelle wie folgt, id Primärschlüssel
ist╔════╦══════╦════════╗
║ id ║ name ║ active ║
╠════╬══════╬════════╣
║ 1 ║ a ║ 0 ║
║ 2 ║ a ║ 1 ║
╚════╩══════╩════════╝
Und wenn ich einen filtered unique index on name where active = 1
haben. Nun möchte ich nur schalten für Zeilen aktiv schalten, erste Zeile inaktiv setzen und zweite Zeile aktiv setzen. Wenn ich versuche, aktualisieren zu tun es
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
es feinen funktioniert. Aber wenn ich versuche, merge zu tun:
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;
wenn fehlgeschlagen mit Fehler Cannot insert duplicate key row in object 'dbo.Table1' with unique index 'ix_Table1'. The duplicate key value is (a)
.
Selbst Fremde, wenn I Tabelle haben wie diese (erste Zeile aktiv haben = 1 und zweiten Reihe haben aktiv = 0):
╔════╦══════╦════════╗
║ id ║ name ║ active ║
╠════╬══════╬════════╣
║ 1 ║ a ║ 1 ║
║ 2 ║ a ║ 0 ║
╚════╩══════╩════════╝
und fusionieren es wie folgt:
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;
Es funktioniert wieder. So sieht es wirklich aus wie Merge Updates Zeile für Zeile durchführt und Indexe nach jeder Zeile überprüft. Ich habe eindeutige Einschränkungen, eindeutige Indizes ohne Filter überprüft, es funktioniert alles in Ordnung. Es kommt nur fehl, wenn ich Merge und gefilterten Index kombiniere.
Also die Frage ist - ist es ein Bug und wenn ja, was ist die beste Umgehungsmöglichkeit dafür?
Sie können es auf sql fiddle demo versuchen.