加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

Microsoft SQL Server(MSSQL)可更新视图,具有多个基表和完整性能

发布时间:2020-12-14 02:50:31 所属栏目:Windows 来源:网络整理
导读:我正在使用MSSQL 2008 R2.它具有可更新视图的便利功能.例如,如果我有一个表t映射id到name: create table t (id int not null primary key,name varchar(100) not null unique) 然后另一个表提供一些ID和更多信息: create table u (id int not null primary
我正在使用MSSQL 2008 R2.它具有可更新视图的便利功能.例如,如果我有一个表t映射id到name:

create table t (id int not null primary key,name varchar(100) not null unique)

然后另一个表提供一些ID和更多信息:

create table u (id int not null primary key references t,info varchar(100) not null)

为了方便起见,这个视图让我可以看到来自u的行,并使用name列进行扩充:

create view v as select u.*,t.name from u u join t t on u.id = t.id

那么我现在可以按名称进行更新,而不是id:

update v set info = 'foo' where name = 'fred'

最方便的.但是,如果我想删除’fred’的行,会发生什么?

delete v where name = 'fred' -- Fails

我收到了错误

View or function ‘v’ is not updatable because the modification affects multiple base tables.

正如SQL Updatable View with joined tables(指的是Oracle,但MSSQL的情况看起来相同)中所述,只要只有一个密钥保留表,就可以在多个基表上拥有可更新的视图.粗略地说,这是表中任何一行在视图中最多出现一次的位置.在上面的视图中,我们可以看到t和u都是密钥保留的表.但我们可以通过调整视图定义来作弊:

create view v as
select u.*,(select t.name from t t where t.id = u.id) as name
from u u

这提供了与以前相同的行,但现在允许更新:

update v set info = 'foo' where name = 'fred'

从语义上讲,t中的任何行在视图中最多出现一次仍然是正确的,但是因为我们没有以正常方式加入t,所以我们没有达到更新限制.此外,我们还可以从此视图中删除:

delete from v where name = 'fred'

这是正确的,从基础表中删除但不从t中删除.显然,由于早期的视图表示为简单连接,因此无法判断“删除”操作是应该从u还是从t(或两者)中删除行.

对于许多“选择”查询,使用重写视图的执行计划有点不同,所以我可能期望它在某些情况下执行速度稍慢.遗憾的是,优化器无法看到(在这种特殊情况下,存在唯一索引)两个视图具有相同的数据.

您还可以使用函数创建可更新的视图:

create function dbo.get_name(@id int) returns varchar(100) as begin
  declare @r varchar(100)
  select @r = name from t where id = @id
  return @r
end

create view v as select *,dbo.get_name(id) as name from u

这可以提供仍然不同(通常更复杂)的查询计划,因此它可能会更慢.

因此,我们有两种可能的方法来制作可更新的视图,但它们并不完全令人满意.让更新和删除操作正常工作会很好,但是要确保视图在选择查询上的性能不会比两个表的简单连接差.也许你可以给查询引擎一些提示.谁能提出建议?

解决方法

(从t t中选择t.name,其中t.id = u.id)是一个非常Macgyver的技巧,你只需要一个表的限制可删除表.

我可以建议的一个解决方案是使用而不是触发器,这将允许您个性化删除语句将对视图执行的操作.

自定义触发器可能不会影响视图的自动优化.

一些网站通过一些例子更深入地了解它:
http://blogs.msdn.com/b/anthonybloesch/archive/2009/02/16/insteadoftriggerspart1.aspx

http://www.mssqltips.com/sqlservertip/1804/using-instead-of-triggers-in-sql-server-for-dml-operations/

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读