Несколько инструкций SQL UPDATE ИЛИ одна с РЕГИСТРОМ в ней?

StackOverflow https://stackoverflow.com/questions/1638051

Вопрос

Я создал триггер, в котором я пытаюсь упорядочить приоритеты и не допускать дублирования значений приоритета.Есть некоторые вещи, которые следует учитывать.

  1. Пользователь может свободно формировать приоритет в.
  2. Ничто не мешает им выбрать тот же приоритет, что и у другого элемента.
  3. Когда вводится значение, равное другому значению, новый элемент с приоритетом должен иметь приоритет в приоритете, а другой элемент должен быть увеличен.

    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

Не должно быть никаких (заметных) различий в производительности, в любом случае вы будете выполнять один оператор обновления для базы данных.

Я решил отказаться от этой идеи и оставляю это на усмотрение пользовательского интерфейса для обновления приоритета. Я прекратил разрешать ввод данных пользователем.

Я не уверен, какие из этих ответов верны, поэтому я отмечу это как правильный и позволю сообществу выяснить это методом проб и ошибок. :)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top