在触发器中访问已删除和已插入表中的字段

时间:2018-10-31 15:11:26

标签: sql-server triggers

我有以下触发器:

CREATE TRIGGER trFoodUpdate ON Food
AFTER UPDATE
AS
    DECLARE @Action nvarchar(1000) = 'Change(s): '

    IF Inserted.FoodID <> Deleted.FoodID THEN SET @Action += CHAR(13) + '-You have updated FoodID from ' + Inserted.FoodID + 'to ' + Deleted.FoodID
    .... --Other IF-s--


    INSERT INTO FoodTriggerTable (FoodID, FoodName, FoodDesc, FoodPrice, Action, InsertActionTime)
    SELECT FoodID, FoodName, FoodDesc, FoodPrice, @Action, GETDATE() FROM Inserted
GO

我正在尝试将更新的FoodIDFoodName等插入我的FoodTriggerTable。但是,我似乎做不到:

IF Inserted.FoodID <> Deleted.FoodID THEN ...

它说“无法绑定多部分标识符” Inserted.FoodID”。 Deleted.FoodID上发生相同的错误。为什么会这样?

我认为我可以使用DECLARE声明临时变量,该临时变量可以存储上述表中的所有所需数据,但是我可以使用上面的方法吗?

编辑

我似乎误解了SQL Server中的许多概念,但是我试图将更新后的FoodIDFoodName和其余字段插入到名为FoodTriggerTable的表中,其中存储了“日志”,其中包含有关记录更新的信息。

我正在尝试插入一个句子,该句子列出FoodFoodTriggerTable表中对记录所做的更改。因此,我尝试设置一个名为@Action的新变量来存储一个字符串,然后将其与其他字符串连接。 @Action包含的字符串然后将使用以下命令插入到Action的{​​{1}}字段中:

FoodTriggerTable

假设我只更新了INSERT INTO FoodTriggerTable (FoodID, FoodName, FoodDesc, FoodPrice, Action, InsertActionTime) SELECT FoodID, FoodName, FoodDesc, FoodPrice, @Action, GETDATE() FROM Inserted 表中的食物价格,我希望Food中的Action字段包含以下字符串:

FoodTriggerTable

所以我要尝试的是连接Change(s): You've changed the food price from 30 to 45

2 个答案:

答案 0 :(得分:2)

Sean的评论已经指出了您的代码所证明的基本误解。

从技术和具体角度来说,出现The multi-part identifier "Inserted.FoodID" could not be bound错误的原因是因为您没有在FROM子句中包含InsertedDeleted

不可能从损坏的代码中获得100%的确定,但是可能需要做的是使用CASE表达式在代码的最终INSERT查询中计算Action列,以便每一行单独处理。

答案 1 :(得分:2)

这是解决此类问题的一种方法的完整示例。它跟踪所有列中的更改。除了示例触发器之外,我还创建了Food和FoodAudit表。然后,我创建了一些数据并对其进行了几次更新,以便您了解其工作原理。

create table Food
(
    FoodID int identity
    , FoodName varchar(100) not null
    , FoodDesc varchar(100) not null
    , FoodPrice decimal(7,2) not null
)

create table FoodAudit
(
    FoodID int not null
    , FoodName varchar(100) not null
    , FoodDesc varchar(100) not null
    , FoodPrice decimal(7,2) not null
    , ChangeDate datetime not null
        CONSTRAINT DF_FoodAudit_ChangeDate DEFAULT getdate()
)

GO

create trigger TR_Food on Food after UPDATE as

    set nocount on;

    insert FoodAudit
    (
        FoodID
        , FoodName
        , FoodDesc
        , FoodPrice
        , ChangeDate
    )
    select d.FoodID
        , d.FoodName
        , d.FoodDesc
        , d.FoodPrice
        , getdate()
    from deleted d

GO

insert Food
(
    FoodName
    , FoodDesc
    , FoodPrice
)
select 'Bacon'
    , 'Yummy'
    , 3.42

GO

update Food
set FoodPrice = 1.23
where FoodName = 'Bacon'

waitfor delay '00:00:02' --used to simulate updates at different times.

update Food
set FoodPrice = 12.23
    , FoodDesc = 'wow'
where FoodName = 'Bacon'

waitfor delay '00:00:02' --used to simulate updates at different times.

update Food
set FoodPrice = 12.23
    , FoodDesc = 'wait'
where FoodName = 'Bacon'

waitfor delay '00:00:02' --used to simulate updates at different times.

update Food
set FoodDesc = 'Yummers'
where FoodName = 'Bacon'

waitfor delay '00:00:02' --used to simulate updates at different times.

select * from FoodAudit