Проблема в том, что вы пытаетесь изменить нумерацию всех строк с более высоким значением столбца ListOrder
, чем у одной из удаленных строк, а не только тех, которые имеют одинаковые LONSId
и LOId
значения 1 .Поэтому нам нужно ужесточить UPDATE
, чтобы лучше нацелить его.
Пока мы на нем, мы можем также сделать корректным удаление нескольких строк триггера тоже:
CREATE TRIGGER REORDONNE
AFTER DELETE ON TEST1_TEST2
AS
BEGIN
;With Ranges as (
select
LONSId,
LOId,
ListOrder,
COUNT(*) OVER (PARTITION BY LONSId,LOId ORDER BY ListOrder) as Cnt,
LAG(ListOrder) OVER (PARTITION BY LONSId,LOId ORDER BY ListOrder desc)
as NextListOrder
from
deleted
)
update t
set ListOrder= t.ListOrder- Cnt
from
TEST1_TEST2 t
inner join
Ranges r
on
t.LONSId = r.LONSId and
t.LOId = r.LOId and
t.ListOrder > r.ListOrder and
(r.NextListOrder is null or r.NextListOrder > t.ListOrder)
END;
Надеюсь, логика здесь ясна.Мы определяем, на какие строки, которые все еще существуют в таблице, должна влиять каждая строка из deleted
, и проверяем, что мы нацеливаемся только на эти строки, учитывая весь ключ .
(Есливаша версия SQL Server не поддерживает LAG
, тогда простой поиск SO должен найти множество примеров для подделки его в более старых версиях. Если он не поддерживает ROW_NUMBER
или CTE
s, то вы можетефальшивые, но на самом деле обновление таких машин уже не пора).
1 Например, в вашем примере delete from TEST1_TEST2 where NSId=13 and Id=1
ваш триггер попытается обновить все строки с помощьюListOrder
больше 1
.Фактический конфликт, о котором вам говорят (или хотя бы один из них), относится к строке с текущим ключом (2,2,2), который также зависит от вашего оператора обновления, но (2,2,1) не была строка, которая была удалена, и поэтому это дублирующее значение ключа.