我想弄清楚我需要在这里使用:删除,插入或更新。
基本上
当主表更新时,我需要将一些数据写入历史表,并且只有当状态从某些内容更改为待处理或活动时才需要。
这就是我现在所拥有的:
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]
所以我希望新数据保留在主表中,历史表将被覆盖的内容更新...现在它只是复制相同的信息。所以更新后,我的两个表都有相同的数据。
答案 0 :(得分:7)
只有Inserted
和Deleted
伪表 - 没有Updated
。
对于UPDATE
,Inserted
包含新值(更新后),而Deleted
包含更新前的旧值。
另外请注意触发器每次启动一次 - 每行不会触发一次。因此,两个伪表都可能包含多行!不要只假设一行并将其分配给变量 - 这个
SELECT @statusOldValue = statusCode FROM deleted
SELECT @statusNewValue= statusCode FROM updated
如果您有多行, 将失败!您需要以Inserted
和Deleted
中的多行的方式编写触发器!
更新:是 - IS 是一种更好的方式来写这个:
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 JOIN
和Inserted
伪表之间创建Deleted
以获取所有已更新的行
在WHERE
SELECT
子句中指定所有其他条件(不同的状态代码等)
此解决方案适用于正在更新的批量行 - 在多行更新时不会失败....
答案 1 :(得分:5)
您需要同时使用inserted
和deleted
表来检查以下记录:
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')
答案 2 :(得分:1)
没有updated
表,您正在寻找inserted
。