我正在尝试创建一个触发器,该触发器在表component
上运行,并将UPDATE
,DELETE
和INSERT
操作记录到表component_history
< / p>
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
中的信息(component
)发送到component_history
?
我试过了:
SET
@tr_id_component = component.id,
@tr_name = component.name,
@tr_value = component.value
但它报告说:
Msg 4104,Level 16,State 1,Procedure component_hist,Line 22
无法绑定多部分标识符“component.id”。
答案 0 :(得分:2)
这样的事情应该足够了:
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
情况下,我们只是存储新值,而不是旧值。
inserted
and deleted
pseudo-tables是特殊的 - 它们包含受导致触发器触发的语句影响的行。 inserted
表包含任何新行,deleted
表包含任何旧行。这导致了这样的逻辑:在insert
期间,deleted
将为空(没有旧行受插入影响)。在delete
期间,inserted
将为空(未创建新行)。在update
期间,将填充两个表。
这就是select
的顶部适用于insert
和update
操作的原因,因为我们使用的是inserted
表。但我们检查deleted
中是否有任何行,以区分这两个操作。在底部select
(union all
下方),我们查询deleted
表 - 但我们使用where
子句来阻止返回任何行,如果这实际上是{ {1}}操作。