日期:2014-01-05  浏览次数:20595 次


       最近常常使用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