Quindi ho scoperto uno strano comportamento di SQL Server oggi.Unione con indice filtrato univoco
Supponiamo che io sono una tabella come questa, id è chiave primaria
╔════╦══════╦════════╗
║ id ║ name ║ active ║
╠════╬══════╬════════╣
║ 1 ║ a ║ 0 ║
║ 2 ║ a ║ 1 ║
╚════╩══════╩════════╝
E supponiamo ho una filtered unique index on name where active = 1
. Ora, voglio solo attivare lo switch per le righe, impostare la prima riga inattiva e impostare la seconda riga attiva. Quando provo a fare aggiornarlo come
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
si funziona bene. Ma se provo a fare unione:
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;
se fallito con l'errore Cannot insert duplicate key row in object 'dbo.Table1' with unique index 'ix_Table1'. The duplicate key value is (a)
.
Anche estraneo, se devo tabella come questa (prima riga sono attivo = 1 e seconda fila hanno attivo = 0):
╔════╦══════╦════════╗
║ id ║ name ║ active ║
╠════╬══════╬════════╣
║ 1 ║ a ║ 1 ║
║ 2 ║ a ║ 0 ║
╚════╩══════╩════════╝
e unire così:
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;
Si funziona ancora. Quindi sembra davvero che merge gli aggiornamenti riga per riga e il controllo di indexe dopo ogni riga. Ho controllato vincoli univoci, indici univoci senza filtro, tutto funziona bene. Fallisce solo quando combino unione e indice filtrato.
Quindi la domanda è: è un bug e se lo è, qual è la soluzione migliore per questo?
Puoi provarlo su sql fiddle demo.