Plusieurs instructions SQL UPDATE OU Single avec CASE?
-
08-07-2019 - |
Question
J'ai créé un déclencheur dans lequel j'essaie de garder les priorités dans l'ordre et de ne pas autoriser les valeurs de priorité en double. Il y a certaines choses à considérer.
- L'utilisateur peut libérer la priorité dans.
- Rien ne les empêche de choisir la même priorité qu'un autre élément.
-
Lorsque vous entrez une valeur égale à une autre valeur, l'élément nouvellement priorisé doit avoir priorité dans la priorité et l'autre doit être incrémenté.
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
Je n’ai pas beaucoup testé ce déclencheur, alors s’il ya des problèmes, n'hésitez pas à en parler. Ce que je veux savoir en fin de compte, c'est si je devrais essayer de convertir cela en une seule mise à jour avec une instruction case. (Si c'est même possible.)
S'il serait plus performant d'en faire une seule instruction UPDATE
, je pourrais vraiment utiliser une main pour le déterminer!
La solution
Vous devez réécrire le déclencheur. Cela suppose qu'un seul enregistrement sera jamais inséré / mis à jour ou supprimé à la fois. Vous ne pouvez pas écrire de déclencheur avec cette hypothèse, les déclencheurs fonctionnent sur des lots de données et non sur des lignes. Vous devez vous inscrire pour insérer et supprimer dans vos mises à jour. Donc oui, j'essayerais d'écrire la mise à jour avec une déclaration de cas.
Et pourquoi est-ce un déclencheur supprimé? Il n’y aura pas d’enregistrement à mettre à jour s’il a été supprimé.
Autres conseils
Assurez-vous de revenir en arrière et de générer une erreur (gravité 16) si @@ ROWCOUNT > 1. Votre déclencheur, tel qu'il est écrit actuellement, causerait beaucoup de corruption de données lorsque l'utilisateur aurait tenté d'insérer, de mettre à jour ou de supprimer plusieurs lignes à la fois.
Cela dit, IronGoofy a raison: vous ne toucherez la table qu’une fois, peu importe la condition. Donc, le diviser en plusieurs instructions rend le code plus facile à lire / plus facile à gérer.
Si vous autorisez la mise à jour simultanée de plusieurs lignes, vous devrez le modifier. La logique peut être intimidante!
Que diriez-vous de cela:
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
Il ne devrait y avoir aucune différence de performances (perceptible), vous ne pourrez en aucun cas émettre une seule instruction de mise à jour dans la base de données.
J'ai décidé d'abandonner cette idée et je laisse le soin à l'interface utilisateur de mettre à jour la priorité. J'ai arrêté d'autoriser les entrées d'utilisateur.
Je ne suis pas sûr de savoir laquelle de ces réponses est correcte, je vais donc marquer ceci comme étant correct et laisser la communauté résoudre le problème par essais et erreurs. :)