Várias instruções SQL UPDATE ou Individual com CASE nele?
-
08-07-2019 - |
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.
- O usuário pode livre formar a prioridade.
- Não há nada impedindo-os de escolher a mesma prioridade como outro item.
-
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!
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. :)