我正在编写一个触发器,我需要检查传入的数据并可能更改它。然后在触发器中我需要使用该新数据进行进一步处理。高度简化的版本看起来像这样:
ALTER TRIGGER [db].[trig_update]
ON [db].[table]
AFTER UPDATE
AS
BEGIN
DECLARE @thisprofileID int
IF (Inserted.profileID IS NULL)
BEGIN
SELECT @thisprofileID=profileID
FROM db.otherTable
WHERE userid = @thisuserID;
UPDATE db.table
SET profileID = @thisprofileID
WHERE userid = @thisuserID;
-- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
END
IF ({conditional})
BEGIN
UPDATE db.thirdTable
SET [profileID] = Inserted.profileID
...{20+ other fields}
FROM Inserted ...{a few joins}
WHERE {various criteria}
END
END
我们遇到的问题是update语句失败,因为Inserted.profileID为null,而thirdTable.profileID设置为不允许空值。 table.profileID永远不会保持为null;如果它被创建为null,则此触发器应捕获它并将其设置为值。但即使我们更新了'table',Inserted仍然具有null值。到目前为止,我觉得为什么会这样。
我不确定如何纠正这个问题。在带有注释X的区域中,我尝试对Inserted表运行更新查询以更新profileID,但这导致错误,因为伪表显然无法更新。这个假设我不正确吗?这将是一个简单的解决方案。
对我来说,下一个最合乎逻辑的解决方案是INSERT INTO表变量来制作Inserted的副本,然后在触发器的其余部分使用它,但由于未定义表变量,因此失败。定义该表变量将需要更多的字段而不是我想要计算的字段,并且在我们需要对“table”的结构进行更改时将会出现一个主要的维护噩梦。因此,假设这是最好的方法,是否有一种简单的方法可以将Inserted的数据和结构复制到表变量中,而无需显式定义结构?
我不认为临时表(我可以轻易插入)是一个很好的解决方案,因为我的有限理解是它们比只存在于触发器内的表变量慢得多。我假设临时表也必须是公共的,并且如果我们的触发器触发两次并且两个实例都需要临时表,则会导致问题。