假设我有两个表,一个“实时”表和一个历史表。实时表格如下:
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
更改的情况下没有发生,因为这些列都允许空值?如果是这样,那么在检查这些列是否存在不等式时,我将如何编写一个将空值考虑在内的条件?
答案 0 :(得分: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
答案 1 :(得分: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就足够了。
答案 2 :(得分:1)
不是问题,但如果没有变化,请考虑停止更新。
如果没有更改,则可以阻止更新。
update live table
set SomeVarChar = 'a'
where SomeVarChar is null or SomeVarChar != 'a'
如果一次只是一条记录而不是一个因素 但全局更新SomeVarChar ='a',当99%的值已经是'a'时,会有很多非更新。
是固定触发器。
如果您遇到性能问题需要考虑的事项。