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.

  1. L'utilisateur peut libérer la priorité dans.
  2. Rien ne les empêche de choisir la même priorité qu'un autre élément.
  3. 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!

Était-ce utile?

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. :)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top