日期:2014-05-17 浏览次数:20762 次
--instead of 触发器和 after
--最好是看帮助
if object_id('tb') is not null
drop table tb
go
create table tb(id int)
go
create trigger tri_tb
on tb
instead of insert
as
begin
--操作前执行,因为没写任何代码,所以没有插入到表tb任何记录
print '0 rows'
end
insert into tb select 1
select * from tb
--0行
----------------------------------------
create trigger tri_tb2
on tb
after insert
as
begin
--操作后执行,插入动作已经完成,这里可以通过取 inserted表的记录,插入到其他表或更新其他表
print '1 rows'
end
insert into tb select 1
select * from tb
--1行
------解决方案--------------------
AFTER
指定触发器只有在触发 SQL 语句中指定的所有操作都已成功执行后才激发。所有的引用级联操作和约束检查也必须成功完成后,才能执行此触发器。
如果仅指定 FOR 关键字,则 AFTER 是默认设置。
不能在视图上定义 AFTER 触发器。
INSTEAD OF
指定执行触发器而不是执行触发 SQL 语句,从而替代触发语句的操作。
在表或视图上,每个 INSERT、UPDATE 或 DELETE 语句最多可以定义一个 INSTEAD OF 触发器。然而,可以在每个具有 INSTEAD OF 触发器的视图上定义视图。
INSTEAD OF 触发器不能在 WITH CHECK OPTION 的可更新视图上定义
------解决方案--------------------
INSTEAD OF 可以理解为代替操作,代替插入,代替删除。 当捕捉到INSERT命令时,执行的是代码内指定的内容,而不是真实插入的内容。 举个例子说明吧: create trigger my_tr on v_tb instead of insert as insert t1(col1,col2) select 2,3 go 不管你插入任何数据在v_tb中,最终插入到t1表的数据是2,3这两个。 create trigger my_tr on v_tb instead of insert as insert t1(col1,col2) select col1,col2 from inserted go 如果这样,最终插入到T1的数据就和你在插入v_tb中是一样的。 delete只是动作不同,原理相同。
------解决方案--------------------
这段看看是有必要的
如果 INSTEAD OF INSERT 视图触发器使用 inserted 表中的数据对基表生成 INSERT,则它应当通过排除 INSERT 语句选择列表中的列忽略这些类型的列值。INSERT 语句可为这些类型的列生成虚值。
例如,因为 INSERT 语句必须为映射到基表中标识列或计算列的视图列指定值,所以它可提供占位符值。INSTEAD OF 触发器在构成将值插入基表的 INSERT 语句时会忽略提供的值。
下面的语句创建表、视图和触发器,以解释这一过程:
CREATE TABLE BaseTable
(PrimaryKey int IDENTITY(1,1)
Color nvarchar(10) NOT NULL,
Material nvarchar(10) NOT NULL,
ComputedCol AS (Color + Material)
)
GO
--Create a view that contains all columns from the base table.
CREATE VIEW InsteadView
AS SELECT PrimaryKey, Color, Material, ComputedCol
FROM BaseTable
GO
--Create an INSTEAD OF INSERT trigger on the view.
CREATE TRIGGER InsteadTrigger on InsteadView
INSTEAD OF INSERT
AS
BEGIN
--Build an INSERT statement ignoring inserted.PrimaryKey and
--inserted.ComputedCol.
INSERT INTO BaseTable
SELECT Color, Material
FROM inserted
END
GO
直接引用 BaseTable 的 INSERT 语句不能为 PrimaryKey 和 ComputedCol 列提供值。例如:
--A correct INSERT statement that skips the PrimaryKey and ComputedCol columns.
INSERT INTO BaseTable (Color, Material)
VALUES (N'Red', N'Cloth')
--View the results of the INSERT statement.
SELECT PrimaryKey, Color, Material, ComputedCol
FROM BaseTable
--An incorrect statement that tries to supply a value for the
--PrimaryKey and ComputedCol columns.
INSERT INTO BaseTable
VALUES (2, N'Green', N'Wood', N'GreenWood')
然而,引用 InsteadView 的 INSERT 语句必须为 PrimaryKey 和 ComputedCol 列提供值:
--A correct INSERT statement supplying dummy values for the
--PrimaryKey and ComputedCol columns.
INSERT INTO InsteadView (PrimaryKey, Color, Material, ComputedCol)
VALUES (999, N'Blue', N'Plastic', N'XXXXXX')
--View the results of the INSERT statement.
SELECT PrimaryKey, Color, Material, ComputedCol
FROM InsteadView
传递到 InsteadTrigger 的 inserted 表由不可为空的 PrimaryKey 和 ComputedCol 列构成,所以引用该视图的 INSERT 语句必须提供那些列的值。值 999 和 N'XXXXXX' 传递到 InsteadTrigger,但是触发器中的 INSERT 语句没有选择 inserted、PrimaryKey 或 ComputedCol,因此忽略该值。实际插入 BaseTable 的行在 PrimaryKey 中有 2,在 ComputedCol