日期:2014-05-17  浏览次数:20643 次

关于 instead of触发器
我想在一个视图上创建一个触发器

但用 after不行

网上查下说得用

Instead of

触发器

我从联机丛书上看了下

但看不懂 是什么意思 

可否请各位帮忙解释下 instead of 触发器 与 after有什么不同

------解决方案--------------------
http://blog.csdn.net/feixianxxx/archive/2009/12/03/4935151.aspx
这里有它们的不同点
------解决方案--------------------
SQL code
--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 的可更新视图上定义

------解决方案--------------------
SQL code
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只是动作不同,原理相同。

------解决方案--------------------
这段看看是有必要的
SQL code
如果 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