0

我想弄清楚我需要在这里使用哪个:删除、插入或更新。

基本上。

我需要在更新主表时将一些数据写入历史表,并且仅当状态从某事变为挂起或活动时。

这就是我现在所拥有的:

ALTER TRIGGER [dbo].[trg_SourceHistory]  ON [dbo].[tblSource]
FOR UPDATE AS  
    DECLARE @statusOldValue char(1) 
    DECLARE @statusNewValue char(1)

    SELECT @statusOldValue = statusCode FROM deleted 
    SELECT @statusNewValue= statusCode FROM updated

    IF (@statusOldValue <> @statusNewValue) AND 
       (@statusOldValue = 'P' or @statusOldValue = 'A')
    BEGIN TRY
       INSERT * INTO tblHistoryTable)  
           select * from [DELETED]

所以我希望新数据保留在主表中,历史表用被覆盖的内容更新......现在它只是复制相同的信息。所以更新后,我的两个表都有相同的数据。

4

3 回答 3

7

只有InsertedDeleted伪表 - 没有Updated.

对于UPDATE,Inserted包含新值(更新后),而Deleted包含更新前的旧值。

另请注意,触发器每批次触发一次- 而不是每行触发一次。所以两个伪表都可能包含多行!不要只假设一行并将其分配给变量 - 这

SELECT @statusOldValue = statusCode FROM deleted 
SELECT @statusNewValue= statusCode FROM updated

如果您有多行,将会失败!您需要以这样一种方式编写您的触发器,以便它们可以在和中处理多行InsertedDeleted

更新:是的 - 有一个更好的方法来写这个:

ALTER TRIGGER [dbo].[trg_SourceHistory]  ON [dbo].[tblSource]
FOR UPDATE 
AS  
   INSERT INTO dbo.tblHistoryTable(Col1, Col2, Col3, ...., ColN)
      SELECT Col1, COl2, Col3, ..... ColN
        FROM Deleted d
        INNER JOIN Inserted i ON i.PrimaryKey = d.PrimaryKey
        WHERE i.statusCode <> d.statusCode
          AND d.statusCode IN ('A', 'P')

基本上:

  • 明确指定要插入的列 - 在INSERT语句以及SELECT检索要插入的数据的语句中 - 以避免任何令人讨厌的意外

  • 创建一个INNER JOINbetweenInsertedDeletedpseudo-tables 以获取所有已更新的行

  • WHERE在_SELECT

此解决方案适用于批量更新的行 - 它不会在多行更新时失败......

于 2011-07-25T18:30:11.427 回答
5

您需要同时使用 theinserteddeleted表来检查以下记录:
1. 已经存在(检查它不是插入)
2. 仍然存在(检查它不是删除)
3. 状态字段已更改

您还需要确保以基于集合的方法执行此操作,根据 marc_s 的回答,触发器不是单个记录过程。

INSERT INTO
  tblHistoryTable
SELECT
  deleted.*
FROM
  inserted
INNER JOIN
  deleted
    ON inserted.PrimaryKey = deleted.PrimaryKey
WHERE
  inserted.StatusCode <> deleted.StatusCode
  AND (inserted.StatusCode = 'P' OR inserted.StatusCode = 'A')
  • 插入 = 新值
  • 已删除 = 旧值
于 2011-07-25T18:47:39.983 回答
1

没有updated桌子,您正在寻找inserted

于 2011-07-25T18:29:58.197 回答