对MSsql Server的view使用instead of trigger进行视图更新
2024-08-31 00:48:04
供稿:网友
最近常常使用view,但mssql server不允许对关联两个基表以上的view进行更新操作。由于项目上的需要,花了一个晚上的时间研究了一下。抽点时间把过程和心得记录下来。
先看看权威说法:
可更新视图:
microsoft sql server 2000 以两种方法增强可更新视图的类别:
instead of 触发器:可以在视图上创建 instead of 触发器,以使视图可更新。执行 instead of 触发器,而不是执行定义触发器的数据修改语句。该触发器使用户得以指定一套处理数据修改语句时需要执行的操作。因此,如果在给定的数据修改语句(insert、update 或 delete)上存在视图的 instead of 触发器,则通过该语句可更新相应的视图。有关 instead of 触发器的更多信息,请参见设计 instead of 触发器。
分区视图:如果视图属于称为"分区视图"的指定格式,则该视图的可更新性受限于某些限制。本主题稍后将讨论分区视图及其可更新性。
必要时,sql server 将"本地分区视图"辨别为所有参与表和视图都在同一 sql server 上的视图,而将"分布式分区视图"辨别为视图中至少有一个表驻留在不同(远程)服务器上的视图。
如果视图没有 instead of 触发器,或者视图不是分区视图,则视图只有满足下列条件才可更新:
select_statement 在选择列表中没有聚合函数,也不包含 top、group by、union(除非视图是本主题稍后要描述的分区视图)或 distinct 子句。聚合函数可以用在 from 子句的子查询中,只要不修改函数返回的值。有关更多信息,请参见聚合函数。
select_statement 的选择列表中没有派生列。派生列是由任何非简单列表达式(使用函数、加法或减法运算符等)所构成的结果集列。
select_statement 中的 from 子句至少引用一个表。select_statement 必须不仅只包含非表格格式的表达式(即不是从表派生出的表达式)。例如,以下视图是不可更新的:
create view notable as
select getdate() as currentdate,
@@language as currentlanguage,
current_user as currentuser
insert、update 和 delete 语句在可以引用可更新视图之前,也必须如上述条件指定的那样满足某些限制条件。只有当视图可更新,并且所编写的 update 或 insert 语句只修改视图的 from 子句引用的一个基表中的数据时,update 和 insert 语句才能引用视图。只有当视图在其 from 子句中只引用一个表时,delete 语句才能引用可更新的视图。
分区视图比较麻烦,本文采用instead of 触发器的方法解决!
我的实验如下:先建立两个表table1、table2。表结构分别如下:
备注:
1, 其中table2中的d字段为自动性,步长为默认值1
2, table1中的a字段为自动性,步长为默认值1
然后,建立视图view1:
select dbo.table2.d, dbo.table2.e, dbo.table1.b, dbo.table1.c
from dbo.table2 inner join
dbo.table1 on dbo.table2.a = dbo.table1.a
显然,该视图包含字段d,e,b,c四个字段
问题很明确?如何向这个视图增加数据呢?几番尝试最终得到正确的sql为:
create trigger trig_ins_view1 on view1
instead of insert
as
declare @a int
declare @b int
begin
set nocount on
insert into table1 select b,c from inserted
select @a=(max(a)+1) from table1
select @b=e from inserted
insert into table2(a,e) values (@a,@b)
end
中国最大的web开发资源网站及技术社区,