Pregunta

He creado un desencadenador donde intento mantener las prioridades en orden y no permitir valores de prioridad duplicados. Hay algunas cosas a considerar.

  1. El usuario puede liberar la forma en la prioridad.
  2. No hay nada que les impida elegir la misma prioridad que otro elemento.
  3. Cuando se ingresa un valor igual a otro valor, el elemento recientemente priorizado debe tener prioridad en la prioridad y el otro debe incrementarse.

    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
    

No he probado mucho este disparador, así que si hay áreas de preocupación, no dude en hablar. Lo que finalmente quiero saber es si debería intentar convertir esto en una única actualización con una declaración de caso. (Si eso es posible).

¡Si fuera más eficiente hacer esto una sola declaración UPDATE , realmente podría usar una mano para resolverlo!

¿Fue útil?

Solución

Necesita reescribir el disparador. Se supone que solo se insertará / actualizará o eliminará un solo registro a la vez. No puede escribir un activador con esa suposición, los activadores operan en lotes de datos, no en filas. Debe unirse a insertado y eliminado en sus actualizaciones. Entonces sí, trataría de escribir la actualización con una declaración de caso.

¿Y por qué es esto un disparador eliminado? No habrá un registro para actualizar si se eliminó.

Otros consejos

Asegúrese de retroceder y generar un error (gravedad 16) si @@ ROWCOUNT > 1. Su activador como está escrito actualmente causaría una gran cantidad de corrupción de datos del usuario que intentó insertar, actualizar o eliminar varias filas a la vez.

Dicho esto, IronGoofy tiene razón: solo tocarás la mesa una vez, independientemente de la condición. Entonces, dividirlo en varias declaraciones hace que el código sea más fácil de leer / más fácil de mantener.

Si permitiera que se actualizaran varias filas a la vez, necesitaría cambiar esto. ¡La lógica puede ser desalentadora!

¿Qué tal esto?

 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

No debería haber ninguna diferencia (notable) de rendimiento, en cualquier caso, emitirá una única declaración de actualización a la base de datos.

Decidí deshacerme de esta idea y lo dejo a la interfaz de usuario para actualizar la prioridad. He dejado de permitir la entrada del usuario.

No estoy seguro de cuáles de estas respuestas son correctas, así que voy a marcar esto como correcto y dejar que la comunidad lo resuelva con prueba y error. :)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top