Несколько инструкций SQL UPDATE ИЛИ одна с РЕГИСТРОМ в ней?
-
08-07-2019 - |
Вопрос
Я создал триггер, в котором я пытаюсь упорядочить приоритеты и не допускать дублирования значений приоритета.Есть некоторые вещи, которые следует учитывать.
- Пользователь может свободно формировать приоритет в.
- Ничто не мешает им выбрать тот же приоритет, что и у другого элемента.
Когда вводится значение, равное другому значению, новый элемент с приоритетом должен иметь приоритет в приоритете, а другой элемент должен быть увеличен.
CREATE TRIGGER dbo.trg_Priority ON dbo.Stories AFTER INSERT,UPDATE,DELETE AS BEGIN SET NOCOUNT ON; -- Insert statements for trigger here DECLARE @StoryId INT DECLARE @OldLocation INT DECLARE @NewLocation INT SELECT @NewLocation = Priority, @StoryId = StoryId FROM INSERTED SELECT @OldLocation = Priority FROM DELETED IF @NewLocation = @OldLocation RETURN; IF @NewLocation IS NULL BEGIN UPDATE Stories SET Priority = Priority - 1 WHERE Priority > @OldLocation END IF @NewLocation > @OldLocation BEGIN UPDATE Stories SET Priority = Priority + 1 WHERE Priority >= @NewLocation AND StoryId <> @StoryId END IF @NewLocation < @OldLocation BEGIN UPDATE Stories SET Priority = Priority + 1 WHERE Priority >= @NewLocation AND Priority < @OldLocation AND StoryId <> @StoryId END END GO
Я не часто тестировал этот триггер, так что, если есть проблемные области, не стесняйтесь высказываться.Что я в конечном счете хочу знать, так это то, должен ли я попытаться преобразовать это в одно обновление с помощью инструкции case.(Если это вообще возможно.)
Если бы было более эффективно сделать это единым UPDATE
утверждение Мне действительно не помешала бы помощь, чтобы разобраться в этом!
Решение
Вам нужно переписать триггер.Предполагается, что одновременно будет вставляться / обновляться или удаляться только одна запись.Вы не можете написать триггер с таким предположением, триггеры работают с пакетами данных, а не с построчными.Вам нужно присоединиться к вставляемым и удаляемым обновлениям.Так что да, я бы попытался написать обновление с помощью инструкции case.
И почему это удаленный триггер?Не будет записи для обновления, если она была удалена.
Другие советы
Убедитесь, что вы выполняли откат и выдавали ошибку (уровень серьезности 16), если @@ ROWCOUNT > 1. Ваш триггер в том виде, в котором он написан в настоящий момент, может привести к значительному повреждению данных, когда пользователь пытался вставить, обновить или удалить несколько строк одновременно.
Тем не менее IronGoofy прав: вы будете прикасаться к столу только один раз, независимо от условий. Таким образом, разбиение его на несколько операторов делает код более легким для чтения / более понятным.
Если вы хотите разрешить одновременное обновление нескольких строк, вам нужно это изменить. Логика может быть пугающей!
Как насчет этого?
UPDATE Stories SET Priority = CASE
WHEN Priority > @OldLocation THEN Priority-1
WHEN Priority >= @NewLocation AND StoryID <> @StoryID THEN Priority+1
WHEN Priority >= @NewLocation AND @Priority < @OldLocation And StoryID <> StoryID THEN Priority +1
END
GO
Не должно быть никаких (заметных) различий в производительности, в любом случае вы будете выполнять один оператор обновления для базы данных. Р>
Я решил отказаться от этой идеи и оставляю это на усмотрение пользовательского интерфейса для обновления приоритета. Я прекратил разрешать ввод данных пользователем.
Я не уверен, какие из этих ответов верны, поэтому я отмечу это как правильный и позволю сообществу выяснить это методом проб и ошибок. :) Р>