触发器中已插入表和已删除表之间的关系

时间:2013-11-18 21:19:05

标签: sql-server tsql triggers

假设我有这张表:

Car
----------------------
Name|Date|Color

主键是NameDate的组合。

在更新时,如果更新行的初始Color为蓝色且新的行为红色,我想保留此更新的跟踪。

这就是我所做的:

ALTER TRIGGER TraceTrigger
ON Car
FOR UPDATE
AS
BEGIN
  INSERT INTO TraceTable
  SELECT
    del.Name,
    del.Date,
    del.Color,
    ins.Name,
    ins.Date,
    ins.Color
  FROM deleted as del
  INNER JOIN inserted as ins
  ON del.Name = ins.Name AND del.Date = ins.Date
  WHERE del.color = 'Blue' AND ins.Color = 'Red'
END 

这个例子非常简单。它表明我需要从更新的行中保留X旧值和X新值的跟踪。

但想象一下如果可以修改Name(我知道我们不应该修改PK,但在这种情况下,它是可能的)。鉴于主键可能会发生变化,有时,INSERTEDDELETED表之间的关系将无效。

那么,当PK可以更新为不同的值时,是否可以保持已删除行和插入行之间的关系?

2 个答案:

答案 0 :(得分:3)

您无需费心记录INSERTEDDELETED。只是INSERTED就是我通常做的事情,否则你最终会得到2条信息。您将在插入时记录它,然后在删除时记录相同的数据。

假设您的表格中只有IDName字段,INSERTEDDELETED的跟踪记录如下:< / p>

OldID  OldName    NewID   NewName
1      Harry      1       Henry
1      Henry      1       James
1      James      1       Thomas

正如您所看到的,您正在加倍数据。左侧2列与右侧列相同,但向上移动了一行。

就主键而言,如果您知道在想要保留历史记录时可能需要更改PK,我强烈建议您在表格中添加代理键(例如ID),这样您就不会改变,这样您可以随意更改名称列。

答案 1 :(得分:1)

你永远不会真正改变主键;从逻辑上讲,您实际上创建了一个新实体(记录/行)。实际上,它是一个全新的东西。

有很多方法可以跟踪这一变化,但这里有两个:

  • 像IDENTITY列一样创建行标识符。它不是真正的代理键,因为代理键应始终为1-1,并带有正确的自然键。如果name + date不是主键而你不能创建一个(yuck - 你有数据库设计问题),请使用此方法。
  • 只要PK中的值发生更改,就会更新跟踪表中的数据以匹配新值。如果您的数据库设计正确,这是正确的解决方案。您可以使用ON UPDATE CASCADE外键约束来实现它。