2014-08-29 15 views
10

Ho un problema con questo trigger. Mi piacerebbe che aggiorni le informazioni richieste solo alla riga in questione (quella che ho appena aggiornato) e non all'intera tabella.SQL Server dopo l'aggiornamento trigger

CREATE TRIGGER [dbo].[after_update] 
    ON [dbo].[MYTABLE] 
    AFTER UPDATE 
    AS 
    BEGIN 
      UPDATE MYTABLE 
      SET mytable.CHANGED_ON = GETDATE(), 
      CHANGED_BY=USER_NAME(USER_ID()) 

Come si riconosce al trigger che questo si applica solo alla riga in questione?

+2

Basta aggiungere un join alla tabella inserita nella sua dichiarazione di aggiornamento in base alla chiave primaria. –

+0

aggiunto un join ma il mio trigger si attiva anche su insert. Questo comportamento normale o cosa? – user3927897

risposta

0

Dovresti poter accedere alla tabella INSERTED e recuperare l'ID o la chiave primaria della tabella. Qualcosa di simile a questo esempio ...

CREATE TRIGGER [dbo].[after_update] ON [dbo].[MYTABLE] 
AFTER UPDATE AS 
BEGIN 
    DECLARE @id AS INT 
    SELECT @id = [IdColumnName] 
    FROM INSERTED 

    UPDATE MYTABLE 
    SET mytable.CHANGED_ON = GETDATE(), 
    CHANGED_BY=USER_NAME(USER_ID()) 
    WHERE [IdColumnName] = @id 

Ecco un link su MSDN sulle INSERTED e DELETED tavoli disponibili quando si utilizzano i trigger: http://msdn.microsoft.com/en-au/library/ms191300.aspx

+2

Kane, questo non è corretto se si aggiornano più righe poiché i valori scalari verranno impostati solo per l'ultima riga nell'insieme e mancheranno tutte le altre righe. –

+0

@SeanGallardy, ahh si hai ragione. Avevo pensato che solo una riga fosse aggiornata.Sai cosa dicono delle ipotesi. – Kane

+3

Con un trigger si dovrebbe SEMPRE dare per scontato che ci siano più righe interessate. –

0

Prima di tutto, il trigger come si vede già sta per aggiornare tutti registrare nella tabella. Non è stato effettuato alcun filtraggio per completare lo scambio delle righe.

In secondo luogo, si presuppone che solo una riga cambi nel batch che non è corretto in quanto potrebbero cambiare più righe.

Il modo per farlo correttamente è quello di utilizzare le tabelle virtuali inseriti e cancellate: http://msdn.microsoft.com/en-us/library/ms191300.aspx

+0

Aggiunto: FROM dbo.mytable INNER JOIN inserito ON mytable.TW_ID = inserito.TW_ID Perché il trigger si attiva anche dopo l'evento insert? – user3927897

-1
CREATE TRIGGER [dbo].[after_update] ON [dbo].[MYTABLE] 
AFTER UPDATE 
AS 
BEGIN 
    DECLARE @ID INT 

    SELECT @ID = D.ID 
    FROM inserted D 

    UPDATE MYTABLE 
    SET mytable.CHANGED_ON = GETDATE() 
     ,CHANGED_BY = USER_NAME(USER_ID()) 
    WHERE ID = @ID 
END 
+2

Questo tipo di trigger non gestirà più operazioni su righe. Se più di 1 riga viene aggiornata, ciò non funzionerà correttamente. –

10

Ecco il mio esempio dopo un test

CREATE TRIGGER [dbo].UpdateTasadoresName 
ON [dbo].Tasadores 
FOR UPDATE 
AS 
     UPDATE Tasadores 
     SET NombreCompleto = RTRIM(Tasadores.Nombre + ' ' + isnull(Tasadores.ApellidoPaterno,'') + ' ' + isnull(Tasadores.ApellidoMaterno,'') ) 
     FROM Tasadores 
    INNER JOIN INSERTED i ON Tasadores.id = i.id 

La tabella speciale inserita avrà le informazioni dal record aggiornato

3

Prova questo (aggiornamento, non dopo l'aggiornamento)

CREATE TRIGGER [dbo].[xxx_update] ON [dbo].[MYTABLE] 
    FOR UPDATE 
    AS 
    BEGIN 

     UPDATE MYTABLE 
     SET mytable.CHANGED_ON = GETDATE() 
      ,CHANGED_BY = USER_NAME(USER_ID()) 
     FROM inserted 
     WHERE MYTABLE.ID = inserted.ID 

    END 
+0

PER L'AGGIORNAMENTO e DOPO L'AGGIORNAMENTO sono identici, entrambi si attivano dopo che l'aggiornamento si è verificato ed è stato eseguito il commit. La tabella inserita contiene tutti i record modificati, come hai notato correttamente. – kuklei

3

E 'molto semplice da fare che, Innanzitutto creare una copia della tabella che il tuo vogliono mantenere il registro per Per esempio avete Tabella dbo .SalesOrder con colonne SalesOrderID, Nome, Cognome, LastModified

La tabella versione archieve dovrebbe essere dbo.SalesOrderVersionArchieve con colonne SalesOrderVersionArhieveId, SalesOrderID, Nome, Cognome, LastModified

Ecco il come si intende impostare un trigger sul tavolo SalesOrder

USE [YOURDB] 
GO 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
-- ============================================= 
-- Author:  Karan Dhanu 
-- Create date: <Create Date,,> 
-- Description: <Description,,> 
-- ============================================= 
CREATE TRIGGER dbo.[CreateVersionArchiveRow] 
    ON dbo.[SalesOrder] 
    AFTER Update 
AS 
BEGIN 

    SET NOCOUNT ON; 
INSERT INTO dbo.SalesOrderVersionArchive 

    SELECT * 
    FROM deleted; 

END 

Ora, se si apportano modifiche nella tabella saleOrder che vi mostrerà il cambiamento nella tabella VersionArchieve

+0

thx per una spiegazione semplice ma efficace – Daidon

1

provare questa soluzione.

DECLARE @Id INT 
    DECLARE @field VARCHAR(50) 

    SELECT @Id= INSERTED.CustomerId  
    FROM INSERTED 

    IF UPDATE(Name) 
    BEGIN 
      SET @field = 'Updated Name' 
    END 

    IF UPDATE(Country) 
    BEGIN 
      SET @field = 'Updated Country' 
    END 

    INSERT INTO CustomerLogs 
    VALUES(@Id, @field) 

non ho controllato questo con la versione precedente di SQL Server, ma questo lavorerò con sql server 2012.

Problemi correlati