У меня в таблице SQL Server есть триггер, который принимает пользовательские обновления и регистрирует их, на случай, если нам нужно вернуться, но есть проблема - PullRequest
0 голосов
/ 24 января 2020

Проблема в том, что иногда в день, когда никто ничего не меняет, случайный пользователь просто заходит на страницу, и триггер сохраняет изменения. Проблема в том, что он не только регистрирует изменения, которые никогда не происходили в тот день / момент (потому что он / она не сделал изменения), но также получает случайные данные из INSERTED / DELETED, как у нас есть журнал изменение 5 мая 2009 г., в котором дата изменения установлена ​​в 2014 г., что является длительным периодом времени go.

Мой триггер похож на приведенный ниже, но без личной информации. Мы смоделировали эту проблему, внеся изменения в день, а затем триггер корректно регистрирует ее, после чего мы меняем дату на нашем компьютере, регистрируемся и немного ждем, чем она записывает что-то случайное. Иногда это занимает много времени, и вход / выход из страниц, но в конечном итоге что-то совершенно случайное появляется из другой даты с длинной go. Спасибо за помощь!

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER TRIGGER [dbo].[tablelog]
ON [dbo].[tablechanged]
AFTER UPDATE
AS
BEGIN 
    declare @OLD_DATA nvarchar(2000);
    declare @NEW_DATA nvarchar(2000);
    declare @Counter    INT;
    declare @Occurrences    INT;
    declare @col varchar(1000);
    declare @SELECDELET nvarchar(2000);
    declare @SELECINSER nvarchar(2000);
    declare @user varchar(50);
    declare @cod int;
    declare @emp INT;
    declare @isReg bit;

    set @Occurrences = (SELECT COUNT(COLUMN_NAME) FROM information_schema.columns WHERE table_name = 'tablechanged')
    set @Counter = 0;
    set @user = (SELECT TOP 1 usuarioUltimaAlteracao FROM INSERTED);
    set @emp = (SELECT TOP 1 empCodigo FROM INSERTED);
    set @cod = (SELECT TOP 1 cedCodigo FROM INSERTED);  
    set @isReg = (SELECT TOP 1 alteracaoViaCadastro FROM INSERTED); 

    SELECT * INTO #Del FROM DELETED
    SELECT * INTO #Ins FROM INSERTED

    if(@isReg = 1)
    begin
        while @Counter < @Occurrences 
        begin
            set @Counter = @Counter + 1;        
            set @col = (select COLUMN_NAME FROM information_schema.columns WHERE table_name = 'tablechanged' and ordinal_position = @Counter);
            select @SELECDELET = 'SELECT @OLD_DATA='+@col+' FROM #Del' ;
            select @SELECINSER = 'SELECT @NEW_DATA='+@col+' FROM #Ins' ;
            exec sp_executesql @SELECDELET, N'@OLD_DATA nvarchar(40) OUTPUT', @OLD_DATA OUTPUT
            exec sp_executesql @SELECINSER, N'@NEW_DATA nvarchar(40) OUTPUT', @NEW_DATA OUTPUT  

            if(@OLD_DATA <> @NEW_DATA)
            begin
                INSERT INTO TABLELOG (OPE_DATE,OPE_USER,OPE_TABLE,OPE_COD,OPE_EMP,OPE_FIELD,OPE,OLD_DATA,NEW_DATA)
                VALUES (getdate(), @user, 'tablechanged', @cod, @emp, @col, 'UPDATE', @OLD_DATA,@NEW_DATA)
            end
        end
    end
END

1 Ответ

0 голосов
/ 24 января 2020

SQL Сервер запускает каждый оператор . Не для каждого ряда. Ваш триггер явно не работает в случае многострочного обновления.

В случае многострочного обновления значение @NEW_DATA после выполнения

SELECT @NEW_DATA='+@col+' FROM #Ins' ;

будет последним значением в #Ins, а без ORDER BY недокументировано, что грести его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...