MSSQL - 触发跟踪表中的特定更改

时间:2014-10-15 06:23:40

标签: sql sql-server sql-server-2008

我有一个存档和用户表。我的目标是跟踪用户表上的更改并将旧用户数据保存到存档。

我疯了一个触发器,但它也应该忽略某些领域。

例如我有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

1 个答案:

答案 0 :(得分:0)

您需要在存档中找到该用户的lsat条目,然后查看是否有任何字段已更改。基本查询是:

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子句稍作修改就可以解决这个问题。