SQL Server после запуска обновления

У меня проблема с этим триггером. Я хотел бы, чтобы он обновил запрашиваемую информацию только к указанной строке (той, которую я только что обновил), а не всей таблице.

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())

Как сообщить триггер, что это относится только к указанной строке?

Ответ 1

Вот мой пример после теста

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

Введенная специальная таблица будет содержать информацию из обновленной записи.

Ответ 2

Попробуйте это (обновление, а не после обновления)

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

Ответ 3

Это очень просто сделать, Сначала создайте копию своей таблицы, в которой хотите сохранить журнал для Например, у вас есть таблица dbo.SalesOrder с столбцами SalesOrderId, FirstName, LastName, LastModified

Ваша архивная таблица версий должна быть dbo.SalesOrderVersionArchieve с столбцами SalesOrderVersionArhieveId, SalesOrderId, FirstName, LastName, LastModified

Вот как настроить триггер в таблице 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

Теперь, если вы внесете какие-либо изменения в таблицу saleOrder, вы увидите изменение в таблице VersionArchieve

Ответ 4

Вы должны иметь доступ к таблице INSERTED и получить первичный ключ ID или таблицы. Что-то похожее на этот пример...

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

Здесь ссылка на MSDN в таблицах INSERTED и DELETED, доступных при использовании триггеров: http://msdn.microsoft.com/en-au/library/ms191300.aspx

Ответ 5

попробуйте это решение.

   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)

Я не проверял это со старой версией sql-сервера, но это будет работать с SQL-сервером 2012 года.

Ответ 6

Во-первых, ваш триггер, как вы уже видите, будет обновлять каждую запись в таблице. Фильтрация не выполняется, чтобы выполнить изменение строк.

Во-вторых, вы предполагаете, что только одна строка изменяется в партии, которая неверна, поскольку несколько строк могут меняться.

Для этого нужно использовать виртуальные вставленные и удаленные таблицы: http://msdn.microsoft.com/en-us/library/ms191300.aspx

Ответ 7

Попробуйте этот скрипт, чтобы создать временную таблицу TESTTEST и наблюдать порядок старшинства при вызове триггеров в следующем порядке: 1) INSTEAD OF, 2) FOR, 3) AFTER

Вся логика помещена в триггер INSTEAD OF, и у меня есть 2 примера того, как вы можете кодировать некоторые сценарии...

Удачи...

CREATE TABLE TESTTEST
(
    ID  INT,
    Modified0 DATETIME,
    Modified1 DATETIME
)
GO
CREATE TRIGGER [dbo].[tr_TESTTEST_0] ON [dbo].TESTTEST
INSTEAD OF INSERT,UPDATE,DELETE
AS
BEGIN
    SELECT 'INSTEAD OF'
    SELECT 'TT0.0'
    SELECT * FROM TESTTEST

    SELECT *, 'I' Mode
    INTO #work
    FROM INSERTED

    UPDATE #work SET Mode='U' WHERE ID IN (SELECT ID FROM DELETED)
    INSERT INTO #work (ID, Modified0, Modified1, Mode)
    SELECT ID, Modified0, Modified1, 'D'
    FROM DELETED WHERE ID NOT IN (SELECT ID FROM INSERTED)

    --Check Security or any other logic to add and remove from #work before processing
    DELETE FROM #work WHERE ID=9 -- because you don't want anyone to edit this id?!?!
    DELETE FROM #work WHERE Mode='D' -- because you don't want anyone to delete any records

    SELECT 'EV'
    SELECT * FROM #work

    IF(EXISTS(SELECT TOP 1 * FROM #work WHERE Mode='I'))
    BEGIN
        SELECT 'I0.0'
        INSERT INTO dbo.TESTTEST (ID, Modified0, Modified1)
        SELECT ID, Modified0, Modified1
        FROM #work
        WHERE Mode='I'
        SELECT 'Cool stuff would happen here if you had FOR INSERT or AFTER INSERT triggers.'
        SELECT 'I0.1'
    END

    IF(EXISTS(SELECT TOP 1 * FROM #work WHERE Mode='D'))
    BEGIN
        SELECT 'D0.0'
        DELETE FROM TESTTEST WHERE ID IN (SELECT ID FROM #work WHERE Mode='D')
        SELECT 'Cool stuff would happen here if you had FOR DELETE or AFTER DELETE triggers.'
        SELECT 'D0.1'
    END

    IF(EXISTS(SELECT TOP 1 * FROM #work WHERE Mode='U'))
    BEGIN
        SELECT 'U0.0'
        UPDATE t SET t.Modified0=e.Modified0, t.Modified1=e.Modified1
        FROM dbo.TESTTEST t
        INNER JOIN #work e ON e.ID = t.ID
        WHERE e.Mode='U'
        SELECT 'U0.1'
    END
    DROP TABLE #work

    SELECT 'TT0.1'
    SELECT * FROM TESTTEST
END
GO
CREATE TRIGGER [dbo].[tr_TESTTEST_1] ON [dbo].TESTTEST
FOR UPDATE
AS
BEGIN
    SELECT 'FOR UPDATE'

    SELECT 'TT1.0'
    SELECT * FROM TESTTEST

    SELECT 'I1'
    SELECT * FROM INSERTED

    SELECT 'D1'
    SELECT * FROM DELETED

    SELECT 'TT1.1'
    SELECT * FROM TESTTEST
END
GO
CREATE TRIGGER [dbo].[tr_TESTTEST_2] ON [dbo].TESTTEST
AFTER UPDATE
AS
BEGIN
    SELECT 'AFTER UPDATE'

    SELECT 'TT2.0'
    SELECT * FROM TESTTEST

    SELECT 'I2'
    SELECT * FROM INSERTED

    SELECT 'D2'
    SELECT * FROM DELETED

    SELECT 'TT2.1'
    SELECT * FROM TESTTEST
END
GO

SELECT 'Start'
INSERT INTO TESTTEST (ID, Modified0) VALUES (9, GETDATE())-- not going to insert
SELECT 'RESTART'
INSERT INTO TESTTEST (ID, Modified0) VALUES (10, GETDATE())--going to insert
SELECT 'RESTART'
UPDATE TESTTEST SET Modified1=GETDATE() WHERE ID=10-- gointo to update
SELECT 'RESTART'
DELETE FROM TESTTEST WHERE ID=10-- not going to DELETE
SELECT 'FINISHED'

SELECT * FROM TESTTEST
DROP TABLE TESTTEST

Ответ 8

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