1

假设我有两个表,一个“实时”表和一个历史表。实时表如下所示:

CREATE TABLE dbo.LiveTable (
    LiveTableId INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
    SomeVarChar VARCHAR(20) NOT NULL DEFAULT '',
    SomeForeignId INT NULL,
    OtherForeingId INT NULL,
    ChangeBy VARCHAR(128) NOT NULL,
    ChangeTime DATETIME NOT NULL DEFAULT GETDATE()
)

历史表看起来一样,除了它有自己的主键和在IsDelete别处使用的列。当用户更新 中的一行时LiveTable,我想在历史表中记录该行的先前值。当然,这很简单,只需一个UPDATE触发器。但我刚刚确定我的一些更新没有触发历史表插入,我相信这是由于允许空值的字段。我的触发器看起来像这样:

CREATE TRIGGER dbo.trgLiveTableUpdate ON dbo.LiveTable FOR UPDATE
AS
INSERT INTO dbo.LiveTableHistory (
    LiveTableId,
    SomeVarChar,
    SomeForeignId,
    OtherForeignId,
    ChangeBy,
    ChangeTime
)
SELECT 
    d.LiveTableId,
    d.SomeVarChar,
    d.SomeForeignId,
    d.OtherForeignId,
    d.ChangeBy,
    d.ChangeTime
FROM DELETED d
JOIN INSERTED i ON d.LiveTableId = i.LiveTableId
WHERE d.SomeVarChar <> i.SomeVarChar
OR d.SomeForeignId <> i.SomeForeignId   //<--- I don't think this works
OR d.OtherForeignId <> i.OtherForeignId //<--- this either

是否有可能我的WHERE条件没有遇到更改的情况,SomeForeignId或者OtherForeignId因为这些列都允许空值?如果是这样,我将如何编写一个在检查这些列是否不相等时考虑空值的条件?

4

3 回答 3

3

您还可以找到 EXCEPTions,它为您提供记录的密钥。

select 
    d.LiveTableId,
    d.SomeVarChar,
    d.SomeForeignId,
    d.OtherForeignId,
    d.ChangeBy,
    d.ChangeTime
from DELETED d
join
(
select LiveTableId, SomeVarChar, SomeForeignId, OtherForeignId from INSERTED
EXCEPT 
select LiveTableId, SomeVarChar, SomeForeignId, OtherForeignId from DELETED
) e on e.LiveTableId = d.LiveTableId
于 2012-10-02T19:04:51.510 回答
2
WHERE d.SomeVarChar <> i.SomeVarChar
OR ISNULL(d.SomeForeignId,-987654) <> ISNULL(i.SomeForeignId,-987654)
OR ISNULL(d.OtherForeignId,-987654) <> ISNULL(i.OtherForeignId,-987654)

*请注意,-987654 只是您 ID 列中的一些未使用的数字。如果它链接回标识列 -1 就足够了。

于 2012-10-02T18:53:49.603 回答
1

不是问题,但如果没有更改,请考虑停止更新。

如果没有更改,则可以阻止更新。

update live table  
set SomeVarChar  = 'a' 
where SomeVarChar is null or SomeVarChar  != 'a'

如果一次只是一条记录,则不是一个因素。
但是当 99% 的值已经是 'a' 时,全局更新 SomeVarChar = 'a' 是很多非更新。

是的,修复触发器。

如果您遇到性能问题,需要考虑一些事情。

于 2012-10-02T20:02:16.007 回答