视图
View(视图)
视图的示例如下:

从而我们不难发现,使用视图将会得到如下好处
- 视图隐藏了底层的表结构,简化了数据访问操作。
- 因为隐藏了底层的表结构,所以大大加强了安全性,用户只能看到视图提供的数据。
- 使用视图,方便了权限管理,让用户对视图有权限而不是对底层表有权限进一步加强了安全性。
- 视图提供了一个用户访问的接口,当底层表改变后,改变视图的语句来进行适应,使已经建立在这个视图上客户端程序不受影响。
普通视图(Rugular View)
普通视图由一个
CREATE VIEW [ schema_name . ] view_name [ (column [ ,...n ] ) ]
[ WITH <view_attribute> [ ,...n ] ]
AS select_statement
[ WITH CHECK OPTION ] [ ; ]
<view_attribute> ::=
{
[ ENCRYPTION ]
[ SCHEMABINDING ]
[ VIEW_METADATA ] }
参数还是比较少的,现在解释一下上面的参数:
-
ENCRYPTION:视图是加密的,如果选上这个选项,则无法修改
. 创建视图的时候需要将脚本保存,否则再也不能修改了 -
SCHEMABINDING:和底层引用到的表进行定义绑定。这个选项选上的话,则视图所引用到的表不能随便更改构架
( 比如列的数据类型) ,如果需要更改底层表构架,则先drop 或者alter 在底层表之上绑定的视图. -
VIEW_METADATA:这个是个很有意思的选项
. 正如这个选项的名称所指示,如果不选择,返回给客户端的metadata 是View 所引用表的metadata, 如果选择了这个选项,则返回View 的metadata. 再通俗点解释,VIEW_METADATA 可以让视图看起来貌似表一样。View 的每一个列的定义等直接告诉客户端,而不是所引用底层表列的定义。 -
WITH Check Option:这个选项用于更新数据做限制,下面会在通过视图更新数据一节解释
.
当然了,创建视图除了需要符合上面的语法规则之外,还有一些规则需要遵守:
- 在
View 中,除非有TOP 关键字,否则不能用Order By 子句( 如果你一意孤行要用Order by, 这里有个hack 是使用Top 100 percent …..) View 在每个Schema 中命名必须独一无二View 嵌套不能超过32 层( 其实实际工作中谁嵌套超过两层就要被打PP 了-.-) Compute,compute by,INTO 关键字不允许出现在View 中View 不能建立在临时表上View 不能对全文索引进行查询
建立
CREATE VIEW v_Test_View1
AS
SELECT TOP 100 * FROM HumanResources.Employee
视图建立完成后,就可以像访问表一样访问视图了
SELECT * FROM v_Test_View1
在


索引视图(Indexed View)
在谈到索引视图之前,我突然想起以前看过的一个漫画

其实索引视图也很类似,在普通的视图的基础上,为视图建立唯一聚集索引,这时这个视图就变成了索引视图
索引视图可以看作是一个和表
对于索引视图也是,为一个视图加上了聚集索引后。视图就不仅仅再是
理解了索引视图的原理之后,我们可以看出,索引视图对于
而同时,每次索引视图所涉及的表进行
谈完了索引视图的基本原理和好处与坏处之后,来看看在
在
比如
- 索引视图涉及的基本表必须
ANSI_NULLS 设置为ON - 索引视图必须设置
ANSI_NULLS 和QUOTED_INDETIFIER 为ON - 索引视图只能引用基本表
SCHEMABINDING 必须设置- 定义索引视图时必须使用
Schema.ViewName 这样的全名 - 索引视图中不能有子查询
avg,max,min,stdev,stdevp,var,varp 这些聚合函数不能用
分割视图(Partitioned View)
分割视图其实从微观实现方式来说,整个视图所返回的数据由几个平行表
分割视图总体上可以分为两种
因为本地分割视图仅仅是为了和
分布式分割视图其实是将由几个由不同数据源或是相同数据源获得的平行数据集进行连接所获得的,一个简单的概念图如下

上面的视图所获得的数据分别来自三个不同数据源的表,每一个表中只包含四行数据,最终组成了这个分割视图
使用分布式分割视图最大的好处就是提升性能
这里要注意的是,分布式分割视图所涉及的表之间的主键不能重复,比如上面的表
还有一点要注意的是,一定要为分布式分割索引的主键加
在微软示例数据库
--create Employee100
SELECT TOP 100 * INTO Employee100
FROM HumanResources.Employee
ORDER BY EmployeeID
--create Employee200
SELECT * INTO Employee200
FROM
(SELECT TOP 100 *
FROM HumanResources.Employee
WHERE EmployeeID NOT IN (SELECT TOP 100 EmployeeID FROM HumanResources.Employee ORDER BY EmployeeID)
ORDER BY HumanResources.Employee.EmployeeID)AS e
这时来建立分布式分割视图
CREATE VIEW v_part_view_test
AS
SELECT * FROM Employee100
UNION
SELECT * FROM Employee200
这时我们对这个索引进行查询操作
SELECT * FROM v_part_view_test
WHERE EmployeeID=105
下面是执行计划

通过上图可以看出,通过这种分割的方式,执行计划仅仅是扫描
所以,当你将不同的数据表之间放到不同的服务器或是使用
使用分布式分割视图能够在所有情况下都提升性能吗?那妥妥的不可能
通过视图(View) 更新数据
通过视图更新数据是我所不推荐的
使用
通过视图来更新数据需要注意以下几点
这里说一下创建
我创建一个

视图(View) 中的几个小技巧
SELECT * FROM sys.sql_modules
WHERE object_id=OBJECT_ID('视图名称')
EXEC sp_refreshview 视图名称
视图(View) 的最佳实践
这是我个人一些经验,欢迎补充
- 一定要将
View 中的Select 语句性能调到最优( 貌似是废话,不过真理都是废话…) View 最好不要嵌套,如果非要嵌套,最多只嵌套一层- 能用存储过程和自定义函数替代
View 的,尽量不要使用View ,存储过程会缓存执行计划,性能更优,限制更少 - 在分割视图上,不要使用聚合函数,尤其是聚合函数还包含了
Distinct - 在视图内,如果
Where 子句能加在视图内,不要加在视图外( 因为调用视图会返回所有行,然后再筛选,性能杀手,如果你还加上了order by …..)
案例
SQL CREATE VIEW 实例
可以从某个查询内部、某个存储过程内部,或者从另一个视图内部来使用视图。通过向视图添加函数、
样本数据库
CREATE VIEW [Current Product List] AS
SELECT ProductID,ProductName
FROM Products
WHERE Discontinued=No
我们可以查询上面这个视图:
SELECT * FROM [Current Product List]
CREATE VIEW [Products Above Average Price] AS
SELECT ProductName,UnitPrice
FROM Products
WHERE UnitPrice>(SELECT AVG(UnitPrice) FROM Products)
我们可以像这样查询上面这个视图:
SELECT * FROM [Products Above Average Price]
另一个来自
CREATE VIEW [Category Sales For 1997] AS
SELECT DISTINCT CategoryName,Sum(ProductSales) AS CategorySales
FROM [Product Sales for 1997]
GROUP BY CategoryName
我们可以像这样查询上面这个视图:
SELECT * FROM [Category Sales For 1997]
我们也可以向查询添加条件。现在,我们仅仅需要查看 “Beverages” 类的全部销量:
SELECT * FROM [Category Sales For 1997]
WHERE CategoryName='Beverages'
SQL 更新视图
您可以使用下面的语法来更新视图:
SQL CREATE OR REPLACE VIEW Syntax
CREATE OR REPLACE VIEW view_name AS
SELECT column_name(s)
FROM table_name
WHERE condition
现在,我们希望向 “Current Product List” 视图添加 “Category” 列。我们将通过下列
CREATE VIEW [Current Product List] AS
SELECT ProductID,ProductName,Category
FROM Products
WHERE Discontinued=No
SQL 撤销视图
您可以通过
SQL DROP VIEW Syntax
DROP VIEW view_name