我创建了一个触发器,该触发器将使用DateTime戳更新文档类型。下面是我的代码
create TRIGGER [dbo].[trg_DocTypeChangeTracking] ON [dbo].[master]
AFTER UPDATE
AS
declare @MasKey int;
declare @DocType varchar(100);
SET NOCOUNT ON
SELECT @MasKey=(SELECT i.MAS_KEY FROM INSERTED i )
IF ( UPDATE(PASSP_ISU) OR UPDATE(PASSP_EXP))
SET @DocType ='Passport'
IF ( UPDATE(RES_ISU) OR UPDATE(RES_EXP))
SET @DocType ='Residency'
IF ( UPDATE(LAB_ID_ISU) OR UPDATE(LAB_ID_EXP))
SET @DocType ='LaborID'
IF ( UPDATE(Emirates_ID_Issue_Date) OR UPDATE(Emirates_ID_Expiry_Date))
SET @DocType ='EmiratesID'
BEGIN
INSERT dbo.tblDocTypeChangeTracking
(
MasKey,
DocType,
DateModified
)
SELECT @MasKey,@DocType,GETDATE()
END
问题是,当更新任何到期日时,它将在具有空值的跟踪表中插入记录。我只需要在同一日期为每个doctype创建一条记录。如何解决此问题。
ID Mas_Key DocType DateModified
1 NULL NULL 2018-11-01
2 NULL NULL 2018-11-01
3 NULL NULL 2018-11-01
4 NULL NULL 2018-11-01
5 73 Passport 2018-11-01
答案 0 :(得分:1)
您需要编写一个可用于 sets 的查询,而不是尝试按程序进行操作。 inserted
和deleted
是伪表,其包含的行数与触发触发器的操作所影响的行数相同。这很容易超过 1 。另外,UPDATE()
回答了一个与我想问的问题不同的问题(它只是有效地告诉您SET
子句中是否提到了该列,而不是值是否已更改)。 / p>
所以,我会写类似的东西:
create TRIGGER [dbo].[trg_DocTypeChangeTracking] ON [dbo].[master]
AFTER UPDATE
AS
declare @MasKey int;
declare @DocType varchar(100);
SET NOCOUNT ON
INSERT dbo.tblDocTypeChangeTracking
(
MasKey,
DocType,
DateModified
)
SELECT
i.mas_key,
DocType,
GETDATE()
from
inserted i
inner join
deleted d
on
i.mas_key = d.mas_key
cross join
(values(1,'Passport'), (2,'Residency')) t(ID,DocType)
where
(t.ID = 1 and i.passp_isu != d.passp_isu) or
(t.ID = 2 and i.res_isu != d.res_isu)
您还将注意到,如果passp_isu
和res_isu
在任何特定行中都发生了更改,我们将产生两行以插入到{{1} }。
现在,由于两个原因,以上内容并不完整。首先,我尚未列出每个tblDocTypeChangeTracking
或每个DocType
的所有条件-我将其作为练习留给您。另外,我假设DocType
等不可为空,并且/或者我们不需要检测passp_isu
-> null
的变化(反之亦然)。在标准SQL中,我将能够编写not null
来执行“ i.passp_isu is different from d.passp_isu
感知”差异检查。不幸的是,在SQL Server中,尚不支持此功能,因此,如果需要支持此类检查,则需要将每个比较写为:
null
哪个漂亮得多