сработать после удаления - PullRequest
0 голосов
/ 24 апреля 2018

Я использую триггер after delete, и он выполняет то, что он обновляет строку при удалении другой; но проблема в том, что при обновлении строки он получает тот же ключ, что и удаленный: но с тех пор триггер after delete сохраняет предполагаемую удаленную строку, и я не могу обновить другую строку из-за нарушения ключа, есть какой-то способ удалить эту строку, и , затем сработает триггер (мне не нужен откат)

так вот мой триггер:

CREATE TRIGGER REORDONNE
AFTER DELETE  ON TEST1_TEST2
AS
BEGIN

DECLARE @oldOrder int

SELECT @oldOrder = ListOrder FROM deleted

UPDATE TEST1_TEST2
SET ListOrder=ListOrder-1
WHERE ListOrder > @oldOrder
END;

и моя таблица TEST1_TEST2 такая:

enter image description here

КЛЮЧ от моей таблицы (LONSId, LOId, ListOrder)

и затем я выполняю этот запрос:

удалить из TEST1_TEST2 где NSId = 13 и Id = 1

проблема в том, что когда я пытаюсь удалить эту 4-ю строку, триггер попытается обновить 5-ю строку и изменить значение ListOrder на 1, но я получаю ошибку KEY, потому что эти 2 строки будут иметь одинаковый ключ, говорящий:

Msg 2627, Niveau 14, État 1, Procédure REORDONNE, Ligne 19

Нарушение де ла противопоставить УНИКАЛЬНЫЙ КЛЮЧ 'IX_TEST1_TEST2'. Невозможно сделать что-либо еще в двух местах: dbo.TEST1_TEST2.

Надеюсь, это достаточно ясно

1 Ответ

0 голосов
/ 24 апреля 2018

Проблема в том, что вы пытаетесь изменить нумерацию всех строк с более высоким значением столбца 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) не была строка, которая была удалена, и поэтому это дублирующее значение ключа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...