1

我正在尝试创建一个在 tablecomponent和 logging上操作的触发器UPDATEDELETE以及INSERT对 table 的操作component_history

CREATE TRIGGER component_hist
ON component
AFTER INSERT, UPDATE, DELETE
AS

DECLARE
   @tr_action varchar(8),
   @tr_id_compoment int,
   @tr_name varchar(max),
   @tr_value int

IF COLUMNS_UPDATED() <> 0 -- delete or update?
BEGIN     
  SET @tr_action = 'UPDATE'
ELSE -- delete     
BEGIN
  SET @tr_action = 'DELETE'
END

INSERT INTO component_history VALUES (@tr_id_component, @tr_name, @tr_value, @tr_action);

如何将id, name, value表中的列()中的信息发送componentcomponent_history

我试过了:

SET 
@tr_id_component = component.id,
@tr_name = component.name,
@tr_value = component.value

但它报告:

消息 4104,级别 16,状态 1,过程 component_hist,第 22 行
无法绑定多部分标识符“component.id”。

4

1 回答 1

3

像这样的东西就足够了:

CREATE TRIGGER component_hist
ON component
AFTER INSERT, UPDATE, DELETE
AS

INSERT INTO component_history /* I'd prefer to see a column list here */
select id,name,value,CASE WHEN EXISTS(select * from deleted) THEN 'UPDATE' ELSE 'INSERT' END
from inserted
UNION ALL
select id,name,value,'DELETE'
from deleted
where not exists(select * from inserted)

一个的优化(如果你有很多的更新)将把EXISTS (select * from deleted)评估移出SELECT(因为它目前每行评估一次)。

另请注意,在这种UPDATE情况下,我们只是存储新值,而不是旧值。


inserteddeleted伪表是特殊的- 它们包含受导致触发器触发的语句影响的行。该inserted表包含任何新行,并且该deleted表包含任何旧行。这导致在 , 期间为空的逻辑insertdeleted没有旧行受插入影响)。在 a 期间deleteinserted将是空的(没有创建新行)。在 期间update,两个表都被填充。

这就是为什么顶部的部分同时select适用于insertupdate操作,因为我们使用的是inserted表。但是我们检查 中是否有行deleted,以区分这两个操作。在底部select(在 下方union all),我们查询deleted表 - 但如果这实际上是一个操作,我们使用该where子句来防止返回任何行。update

于 2012-05-30T07:21:18.153 回答