2012-08-27 11 views
70

Guardando altri esempi ho trovato il seguente ma non sembra funzionare come vorrei: voglio aggiornare solo le informazioni modificate se il valore QtyToRepair è stato aggiornato ... ma non lo fa.Attivazione dell'aggiornamento SQL solo quando la colonna viene modificata

Se commento la dove, le informazioni modificate vengono aggiornate in ogni caso. Come ho detto altri esempi mi hanno portato ad essere ottimista. Ogni indizio è apprezzato. Grazie.

Walter

ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified] 
    ON [dbo].[SCHEDULE] 
    AFTER UPDATE 
AS 
BEGIN 
    SET NOCOUNT ON; 

    UPDATE SCHEDULE SET modified = GETDATE() 
     , ModifiedUser = SUSER_NAME() 
     , ModifiedHost = HOST_NAME() 
    FROM SCHEDULE S 
    INNER JOIN Inserted I on S.OrderNo = I.OrderNo and S.PartNumber = I.PartNumber 
    WHERE S.QtyToRepair <> I.QtyToRepair 
END 
+1

Cosa DB stai usando? –

+1

si aggira come server sql –

+7

Un avviso su 'update()' - verifica solo se la colonna viene visualizzata nell'elenco di aggiornamento ed è sempre true per gli inserimenti. Non controlla se il valore della colonna è cambiato, perché potresti avere più di una riga, dove alcuni valori sono cambiati e altri no. –

risposta

93

avete due modo per la tua domanda:

1- Usa comando Aggiorna nel trigger.

ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified] 
    ON [dbo].[SCHEDULE] 
    AFTER UPDATE 
AS BEGIN 
    SET NOCOUNT ON; 
    IF UPDATE (QtyToRepair) 
    BEGIN 
     UPDATE SCHEDULE 
     SET modified = GETDATE() 
      , ModifiedUser = SUSER_NAME() 
      , ModifiedHost = HOST_NAME() 
     FROM SCHEDULE S INNER JOIN Inserted I 
     ON S.OrderNo = I.OrderNo and S.PartNumber = I.PartNumber 
     WHERE S.QtyToRepair <> I.QtyToRepair 
    END 
END 

2- Usa join tra tabella inserita e tabella eliminata

ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified] 
    ON [dbo].[SCHEDULE] 
    AFTER UPDATE 
AS BEGIN 
    SET NOCOUNT ON;  

    UPDATE SCHEDULE 
    SET modified = GETDATE() 
     , ModifiedUser = SUSER_NAME() 
     , ModifiedHost = HOST_NAME() 
    FROM SCHEDULE S 
    INNER JOIN Inserted I ON S.OrderNo = I.OrderNo and S.PartNumber = I.PartNumber 
    INNER JOIN Deleted D ON S.OrderNo = D.OrderNo and S.PartNumber = D.PartNumber     
    WHERE S.QtyToRepair <> I.QtyToRepair 
    AND D.QtyToRepair <> I.QtyToRepair 
END 

Quando si utilizza il comando update per la tavola SCHEDULE e Imposta QtyToRepair Colonna al nuovo valore, se il nuovo valore pari al valore precedente in uno o multi riga, soluzione 1 aggiorna tutta la riga aggiornata nella tabella Schedule ma la soluzione 2 aggiorna solo le righe che il vecchio valore non è uguale al nuovo valore.

+0

Ci scusiamo per non aver menzionato che si trattava di SQLServer. Avevo bisogno di usare la tabella cancellata. Ho finito per scrivere su un tavolo separato (per mantenere una cronologia). –

+5

L'approccio n. 2 è migliore, se non si desidera attivare il trigger se la colonna viene modificata con lo stesso valore. – Neolisk

+0

Penso che possa mancare qualcosa - ma l'approccio n. 1 non funzionerebbe, perché questo è * dopo * l'aggiornamento, quindi la riga corrente avrebbe sempre lo stesso valore della riga di inserimento. È necessario * unirsi a cancellato se si sta utilizzando dopo l'aggiornamento – Rob

5

si vuole fare il seguente:

ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified] 
    ON [dbo].[SCHEDULE] 
    AFTER UPDATE 
AS 
BEGIN 
SET NOCOUNT ON; 

    IF (UPDATE(QtyToRepair)) 
    BEGIN 
     UPDATE SCHEDULE SET modified = GETDATE() 
      , ModifiedUser = SUSER_NAME() 
      , ModifiedHost = HOST_NAME() 
     FROM SCHEDULE S 
     INNER JOIN Inserted I ON S.OrderNo = I.OrderNo AND S.PartNumber = I.PartNumber 
     WHERE S.QtyToRepair <> I.QtyToRepair 
    END 
END 

prega di notare che questo trigger scatterà ogni volta che si aggiorna la colonna, non importa se il valore è lo stesso o no.

11

Si dovrebbe verificare se QtyToRepair viene aggiornato in un primo momento.

ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified] 
    ON [dbo].[SCHEDULE] 
    AFTER UPDATE 
AS 
BEGIN 
SET NOCOUNT ON; 
    IF UPDATE (QtyToRepair) 
    BEGIN 
     UPDATE SCHEDULE 
     SET modified = GETDATE() 
      , ModifiedUser = SUSER_NAME() 
      , ModifiedHost = HOST_NAME() 
     FROM SCHEDULE S INNER JOIN Inserted I 
      ON S.OrderNo = I.OrderNo and S.PartNumber = I.PartNumber 
     WHERE S.QtyToRepair <> I.QtyToRepair 
    END 
END 
10

FYI Il codice ho finito con:

IF UPDATE (QtyToRepair) 
    begin 
     INSERT INTO tmpQtyToRepairChanges (OrderNo, PartNumber, ModifiedDate, ModifiedUser, ModifiedHost, QtyToRepairOld, QtyToRepairNew) 
     SELECT S.OrderNo, S.PartNumber, GETDATE(), SUSER_NAME(), HOST_NAME(), D.QtyToRepair, I.QtyToRepair FROM SCHEDULE S 
     INNER JOIN Inserted I ON S.OrderNo = I.OrderNo and S.PartNumber = I.PartNumber 
     INNER JOIN Deleted D ON S.OrderNo = D.OrderNo and S.PartNumber = D.PartNumber 
     WHERE I.QtyToRepair <> D.QtyToRepair 
end 
+1

Ho trovato utile questo perché il ** 2- Usa Join tra ** la risposta sopra non ha mai funzionato a causa del dove criteri 'WHERE S.QtyToRepair <> I.QtyToRepair E D.QtyToRepair <> I.QtyToRepair' non si attiva mai/matching poiché il primo criterio non è mai stato true - la tabella inserita corrisponde sempre al valore effettivo della tabella. L'utilizzo di 'WHERE I.QtyToRepair <> D.QtyToRepair' è stata la chiave per me. Anche l'aiuto 'IF UPDATE (field)' da inneschi multipli. – Firegarden

Problemi correlati