Pergunta

Eu construí um gatilho onde eu estou tentando manter as prioridades em ordem e não permitir valores de prioridade duplicados. Há algumas coisas a considerar.

  1. O usuário pode livre formar a prioridade.
  2. Não há nada impedindo-os de escolher a mesma prioridade como outro item.
  3. Quando um valor é inserido igual a outro valor do item recém-priorizados deve ter precedência na prioridade eo outro deve ser incrementado.

    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
    

Eu não testei o gatilho muito isso, se há áreas de preocupação à vontade para falar. O que em última análise, quero saber é se eu deveria tentar converter isso em uma única atualização com uma declaração caso. (Se isso é mesmo possível.)

Se seria mais performance para tornar isso uma única instrução UPDATE Eu poderia realmente usar uma mão descobrir isso!

Foi útil?

Solução

Você precisa reescrever o gatilho. Ele assume apenas um registros nunca vai ser inserido / atualizado ou delted no atime. Você não pode escrever um gatilho com essa suposição, gatilhos operar em lotes de dados não row-byrow. Você precisa se juntar para inseridos e excluídos em suas atualizações. Então, sim, eu iria tentar escrever a atualização com uma declaração caso.

E gatilho porque é que este um excluído? Não ganhou;. T ser arecord a atualização se ele foi excluído

Outras dicas

Certifique-se de reverter e gerar um erro (gravidade 16) se @@ ROWCOUNT> 1. Seu gatilho como atualmente escrito iria causar uma grande dose de corrupção de dados do usuário tentou inserir, atualizar ou excluir várias linhas ao mesmo tempo.

Dito isso, IronGoofy está certo: você só vai estar tocando a mesa uma vez, independentemente se a condição. Então, quebrando-a em várias instruções torna o código mais fácil de ler / mais sustentável.

Se você fosse para permitir que várias linhas a ser atualizado ao mesmo tempo, você precisa mudar isso. A lógica pode ser assustador!

Como sobre isto:

 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

Não deve haver qualquer (notável) diferença de desempenho, em qualquer caso, você estará emitindo uma única instrução de atualização no banco de dados.

Eu decidi abandonar essa idéia, e eu deixá-lo até a interface do usuário para atualizar a prioridade. Eu parei permitindo a entrada do usuário.

Eu não tenho certeza qual destas respostas estão corretas, então eu vou marcar este como correta e deixe a figura comunidade lo com tentativa e erro. :)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top