Più istruzioni SQL UPDATE O singole con CASE in esso?
-
08-07-2019 - |
Domanda
Ho creato un trigger in cui sto cercando di mantenere le priorità in ordine e di non consentire valori di priorità duplicati. Ci sono alcune cose da considerare.
- L'utente può liberare la priorità in.
- Non c'è nulla che impedisca loro di scegliere la stessa priorità di un altro oggetto.
-
Quando viene inserito un valore uguale a un altro valore, l'elemento con la nuova priorità dovrebbe avere la precedenza nella priorità e l'altro dovrebbe essere incrementato.
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
Non ho provato molto questo trigger, quindi se ci sono aree di preoccupazione sentiti libero di parlare. Quello che alla fine voglio sapere è se dovrei provare a convertirlo in un singolo aggiornamento con un'istruzione case. (Se è persino possibile.)
Se sarebbe più performante rendere questa una singola istruzione UPDATE
potrei davvero usare una mano per capirlo!
Soluzione
Devi riscrivere il trigger. Presuppone che un solo record verrà mai inserito / aggiornato o eliminato al momento. Non è possibile scrivere un trigger con tale presupposto, i trigger funzionano su batch di dati non righe di riga. Devi iscriverti a inserito ed eliminato nei tuoi aggiornamenti. Quindi sì, proverei a scrivere l'aggiornamento con un'istruzione case.
E perché si tratta di un trigger eliminato? Non ci sarà; è necessario aggiornare se è stato eliminato.
Altri suggerimenti
Assicurati di eseguire il rollback e generare un errore (gravità 16) se @@ ROWCOUNT > 1. Il trigger come attualmente scritto provocherebbe una grande corruzione dei dati dell'utente che ha tentato di inserire, aggiornare o eliminare più righe contemporaneamente.
Detto questo, IronGoofy ha ragione: toccherai il tavolo solo una volta, indipendentemente dalle condizioni. Quindi, dividerlo in più istruzioni rende il codice più facile da leggere / più gestibile.
Se si dovesse consentire l'aggiornamento di più righe contemporaneamente, è necessario modificarlo. La logica potrebbe essere scoraggiante!
Che ne dici di questo:
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
Non dovrebbero esserci differenze di prestazioni (evidenti), in ogni caso verrà emessa una singola istruzione di aggiornamento nel database.
Ho deciso di abbandonare questa idea e la lascio all'interfaccia utente per aggiornare la priorità. Ho smesso di consentire l'input dell'utente.
Non sono sicuro di quali di queste risposte siano corrette, quindi lo segnerò come corretto e lascerò che la comunità lo capisca con tentativi ed errori. :)