2014-10-15 2 views
0

У меня есть таблицы архива и пользователя. Моя цель - отслеживать изменения в таблице User и сохранять старые данные пользователя в Архиве.MSSQL - триггер для отслеживания конкретных изменений в таблице

Я сумасшедший спусковой крючок, но он также должен игнорировать некоторые поля.

Например, у меня есть last_login_date, поэтому я не хочу создавать новую запись в архиве для каждого входа пользователя.

Как добавить и отслеживать такие условия?

CREATE TRIGGER UserUpdateDataTrigger ON Users.[User] 
FOR UPDATE 
AS 
BEGIN 
    SET NOCOUNT ON 

    DECLARE @User_id int 
    SELECT @User_id = id from inserted 

    -- Add an entry to archive 
    INSERT INTO 
     Users.Archive (name, email, user_id, user_type) 
    SELECT 
     u.name, u.email, u.id, u.user_type 
    FROM 
     Users.[User] u 
    WHERE u.id = @User_id 
END 
GO 

Мой новый код:

USE [SQL_Tutorial] 

IF OBJECT_ID ('Users.UserUpdateDataTrigger', 'TR') IS NOT NULL 
    DROP TRIGGER Users.UserUpdateDataTrigger; 

GO 
/****** Object: Trigger [Users].[UserUpdateDataTrigger] Script Date: 2014-10-15 09:34:17 ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE TRIGGER [Users].[UserUpdateDataTrigger] ON [Users].[User] 
FOR UPDATE 
AS 
BEGIN 
    SET NOCOUNT ON 
    -- Add an entry to archive 

    IF (UPDATE(name) OR UPDATE(email) OR UPDATE(user_type) OR UPDATE(is_active) OR UPDATE(country_id)) 

     BEGIN 
      DECLARE @User_id int; 

      DECLARE @User_name varchar(max); 
      DECLARE @User_email varchar(max); 
      DECLARE @User_user_type int; 
      DECLARE @User_is_active bit; 
      DECLARE @User_country_id int; 

      SELECT @User_id = id from deleted 
      SELECT @User_name = name from deleted 
      SELECT @User_email = email from deleted 
      SELECT @User_user_type = user_type from deleted 
      SELECT @User_is_active = is_active from deleted 
      SELECT @User_country_id = country_id from deleted 

      INSERT INTO 
       Users.Archive (name, email, user_id, user_type, is_active, country_id) 
      VALUES 
       (@User_name, @User_email, @User_id, @User_user_type, @User_is_active, @User_country_id) 
     END 

END 
+0

http://msdn.microsoft.com/en-us/library/bb933875(v=sql.105).aspx –

+0

Поле last_login_date доступно в таблице Users? Если да, хотите ли вы отслеживать last_login_date у пользователей, но без добавления нового столбца в архивной таблице? Дайте мне знать, если я правильно понял. –

+0

Это то, что вам нужно, добавьте свои столбцы соответственно. http://stackoverflow.com/questions/12137102/sql-update-trigger-only-when-column-is-modified – Recursive

ответ

0

Вы должны найти ПОСЛЕДНИЙ запись для пользователя в архиве, а затем посмотреть, какие поля изменились. Основной запрос:

with aui as (
     select au.*, row_number() over (partition by user_id order by achive_id desc) as seqnum, 
      i.name as i_name, i.email as i_email, i.user_type as i.user_type 
     from user.archive au join 
      inserted i 
      on u.user_id = i.user_id 
    ) 
insert into users.archive(name, email, user_id, user_type) 
    select name, email, user_id, user_type 
    from aui 
    where seqnum = 1 and 
      (i_name <> name or i_email <> email or i_user_type <> user_type) 

Две ноты. Во-первых, это предполагает, что у вас есть столбец идентификаторов в archive, чтобы вы могли найти последнюю вставленную строку для данного пользователя. Для вашей логики это очень важно. Во-вторых, вышеуказанная логика не обрабатывает значения NULL, хотя небольшая модификация предложения where может исправить это.

Смежные вопросы