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.

  1. L'utente può liberare la priorità in.
  2. Non c'è nulla che impedisca loro di scegliere la stessa priorità di un altro oggetto.
  3. 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!

È stato utile?

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top