SQL 为值更改的列保存影子表

Posted

技术标签:

【中文标题】SQL 为值更改的列保存影子表【英文标题】:SQL saving shadow table for a column on value change 【发布时间】:2021-06-14 17:34:18 【问题描述】:

我现在拥有的代码可以正确更新影子表,但我遇到的唯一问题是,如果电子邮件值相同,它仍然会更新影子表。这不是我想要的。仅当电子邮件更改未更新时,我才需要更新影子表,我该怎么做?例如,“email@email.com”的原始值只有在表格更改为“secoundemail@gmail.com”等不同的值时才会更新

CREATE TRIGGER AspNetUsersEmail_trigger
ON AspNetUsers
AFTER UPDATE 
AS
*  IF ( UPDATE (Email) )* what could I use here instead of update?
    BEGIN
    INSERT INTO [dbo].[AspNetUserEmailAudit]([UserId],[UserName],[Email],[NormalizedEmail],[FirstName],[LastName])
    SELECT Id,[UserName],[Email],[NormalizedEmail],[FirstName],[LastName] 
    FROM INSERTED
    END;

【问题讨论】:

您知道该怎么做,因为您上一个问题的答案包含您需要的逻辑。 这是错误的数据库@SMor “数据库”无关紧要 - 您的评论毫无意义。 IF UPDATE 没有按照您的想法执行 - 一个常见的误解。您需要比较“之前”和“之后”版本以了解是否确实发生了变化。正如您上一个问题的答案中所给出的,您在主键列上加入了插入和删除的表,并比较了电子邮件列。 【参考方案1】:

您需要比较inserteddeleted 表以检查数据是否实际已更改。

在仍然考虑空值的情况下执行此操作的最简单方法是使用EXCEPT。确保与相同的主键进行比较。

请注意,您仍然可以使用IF(UPDATE 作为提前退出条件,但只有在该列根本不存在时才会退出。如果该列存在但数据未更改,则它将不起作用。

CREATE TRIGGER AspNetUsersEmail_trigger
ON AspNetUsers
AFTER UPDATE 
AS

SET NOCOUNT ON;

IF (UPDATE(Email))
    INSERT INTO [dbo].[AspNetUserEmailAudit]
        (UserId, UserName, Email, NormalizedEmail, FirstName, LastName)
    SELECT Id, UserName, Email, NormalizedEmail, FirstName, LastName
    FROM inserted i
    WHERE EXISTS (SELECT i.Id, i.Email   -- always include the primary key
                  EXCEPT
                  SELECT d.Id, d.Email
                  FROM deleted d);

GO

【讨论】:

以上是关于SQL 为值更改的列保存影子表的主要内容,如果未能解决你的问题,请参考以下文章

全链路压测:影子库与影子表之争

从影子表到原始表的 SQLite Rtree 映射 id(s)

影子文件

我只想在我的表的电子邮件列更新时制作一个表审计/影子表

在 MySQL(或其他 SQL 引擎)中存储历史(影子)表的有效方法

SQL Case when 的使用方法(转自博客园:影子网络科技有限公司)