Mehrere SQL UPDATE-Anweisungen oder Single mit CASE in ihm?
-
08-07-2019 - |
Frage
Ich habe einen Trigger gebaut, wo ich Prioritäten zu halten, um versuchen und erlaubt keine doppelten Prioritätswerten. Es gibt einige Dinge zu beachten.
- Der Benutzer kann die Priorität freier Form in.
- Es gibt nichts, um sie von der Kommissionierung die gleiche Priorität wie ein anderes Element zu blockieren.
-
Wenn ein Wert auf einem anderen Wert gleich das neu priorisierten Objekt hat Vorrang in der eingetragene Priorität ist, soll und der andere soll erhöht werden.
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
Ich habe nicht diesen Trigger eine ganze Menge getestet, so, wenn es Bereiche, die frei fühlen zu sprechen. Was ich will schließlich wissen, ob ich versuchen sollte, und wandeln diese zu einem einzigen Update mit einer Case-Anweisung. (Wenn das auch möglich.)
Wenn es würde mehr performant sein, diese eine einzige UPDATE
Aussage zu machen ich wirklich eine Hand Bezifferung es verwenden könnte aus!
Lösung
Sie müssen die Trigger neu zu schreiben. Er geht davon aus nur einem Datensätze jemals an atime eingefügt / aktualisiert oder delted werden. Sie können keinen Trigger mit dieser Annahme schreiben, arbeiten Trigger auf Chargen von Daten nicht zeilen byrow. Sie müssen eingefügt verbinden und in Ihren Updates gelöscht. Also ja, ich würde versuchen, das Update mit einer Case-Anweisung zu schreiben.
Und warum ist dies ein gelöschtes Trigger? Dort gewann;. T arecord zu aktualisieren, wenn es gelöscht wurde
Andere Tipps
Stellen Sie sicher, dass Sie ein Rollback und heben einen Fehler (Schweregrad 16), wenn @@ ROWCOUNT> 1. Ihr Trigger geschrieben, wie sie derzeit eine große Menge an Daten Korruption des Benutzers verursachen würde versucht, einfügen, aktualisieren oder mehrere Zeilen auf einmal löschen.
Das heißt, IronGoofy richtig ist: Sie wird nur einmal auf den Tisch berühren, unabhängig davon, ob die Bedingung. Also, es heraus in mehrere Anweisungen zu brechen macht den Code leichter zu lesen / mehr wartbar.
Wenn Sie mehr Zeilen zu ermöglichen, waren auf einmal aktualisiert werden, würden Sie brauchen, um dies zu ändern. Die Logik kann entmutigend sein!
Wie wäre es damit:
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
Es sollte kein (spürbar) Unterschied in der Leistung sein, in jedem Fall werden Sie eine einzelne Update-Anweisung an die Datenbank herausgeben.
ich beschlossen, diese Idee zu Graben, und ich überlasse es dem UI, um die Priorität zu aktualisieren. Ich habe aufgehört, eine Benutzereingabe zu ermöglichen.
Ich bin nicht sicher, welche dieser Antworten richtig sind, so werde ich dies als richtig markieren und die Gemeinschaft Figur es aus mit Versuch und Irrtum lassen. :)