视图

视图是一个虚拟表,其内容由查询定义。

视图的作用

  1. 对于视图所引用的基础表来说,视图的作用类似于筛选。定义视图的筛选可以来自:当前或者其他数据库的一个或多个表或者视图。
  2. 视图通常用来集中、简化和自定义每个用户对数据库的不同认识。视图可用作安全机制,方法是允许用户通过视图访问数据,而不授予用户直接访问视图基础表的权限。视图可用于提供向后兼容接口来模拟曾经存在但其架构已更改的表。还可以在向SQL sever 复制数据和从其中复制数据时使用视图,以便提高性能并对数据进行分区。

视图的类型

  • 索引视图:索引视图是被具体化了的视图。可以为视图创建索引,即对视图创建一个唯一索引。索引视图可以显著提高某些类型查询的性能。索引视图尤其适于聚合许多行的查询,但它们不适于经常更新的基本数据集。
  • 分区视图:分区视图在一台或多台服务器间水平连接一组成员表中的分区数据。这样,数据看上去如同来自同一个表。
  • 系统视图:系统视图公开目录元数据。可以使用系统视图返回与SQL server实例或在该实例中定义的对象有关的信息。例如,查询sys.databases 目录视图以便返回与实例中提供的用户定义数据库有关的信息。

1.创建视图

USE AdventureWorks2012 ;   
GO  
CREATE VIEW HumanResources.EmployeeHireDate  
AS  
SELECT p.FirstName, p.LastName, e.HireDate  
FROM HumanResources.Employee AS e JOIN Person.Person AS  p  
ON e.BusinessEntityID = p.BusinessEntityID ;   
GO  
-- Query the view  
SELECT FirstName, LastName, HireDate  
FROM HumanResources.EmployeeHireDate  
ORDER BY LastName;

2.创建索引视图

对视图创建的第一个索引必须是唯一聚集索引。创建唯一聚集索引后,可以创建更多非聚集索引。

为视图创建唯一聚集索引可以提高查询性能,因为视图在数据库中的存储方式与具有聚集索引的表的存储方式相同。

以下示例将创建一个视图并为该视图创建索引。 包含两个查询,它们使用 AdventureWorks 数据库中的索引视图。

--Set the options to support indexed views.设置这些选项来支持索引视图
SET NUMERIC_ROUNDABORT OFF;
SET ANSI_PADDING, ANSI_WARNINGS, CONCAT_NULL_YIELDS_NULL, ARITHABORT,
   QUOTED_IDENTIFIER, ANSI_NULLS ON;
--Create view with schemabinding.
IF OBJECT_ID ('Sales.vOrders', 'view') IS NOT NULL
   DROP VIEW Sales.vOrders ;
GO
CREATE VIEW Sales.vOrders
   WITH SCHEMABINDING
   AS  
      SELECT SUM(UnitPrice*OrderQty*(1.00-UnitPriceDiscount)) AS Revenue,
         OrderDate, ProductID, COUNT_BIG(*) AS COUNT
      FROM Sales.SalesOrderDetail AS od, Sales.SalesOrderHeader AS o
      WHERE od.SalesOrderID = o.SalesOrderID
      GROUP BY OrderDate, ProductID;
GO
--Create an index on the view.在视图上创建索引
CREATE UNIQUE CLUSTERED INDEX IDX_V1
   ON Sales.vOrders (OrderDate, ProductID);
GO
--This query can use the indexed view even though the view is
--not specified in the FROM clause.
SELECT SUM(UnitPrice*OrderQty*(1.00-UnitPriceDiscount)) AS Rev,
   OrderDate, ProductID
FROM Sales.SalesOrderDetail AS od
JOIN Sales.SalesOrderHeader AS o
   ON od.SalesOrderID=o.SalesOrderID
      AND ProductID BETWEEN 700 and 800
      AND OrderDate >= CONVERT(datetime,'05/01/2002',101)
   GROUP BY OrderDate, ProductID
   ORDER BY Rev DESC;
GO
--This query can use the above indexed view.
SELECT OrderDate, SUM(UnitPrice*OrderQty*(1.00-UnitPriceDiscount)) AS Rev
FROM Sales.SalesOrderDetail AS od
JOIN Sales.SalesOrderHeader AS o
   ON od.SalesOrderID=o.SalesOrderID
      AND DATEPART(mm,OrderDate)= 3
      AND DATEPART(yy,OrderDate) = 2002
    GROUP BY OrderDate
    ORDER BY OrderDate ASC;

3.修改视图

修改视图时,无需删除并重新创建视图。

USE AdventureWorks2012 ;  
GO  
-- Create a view.  创建视图
CREATE VIEW HumanResources.EmployeeHireDate  
AS  
SELECT p.FirstName, p.LastName, e.HireDate  
FROM HumanResources.Employee AS e JOIN Person.Person AS  p  
ON e.BusinessEntityID = p.BusinessEntityID ;   

-- Modify the view by adding a WHERE clause to limit the rows returned.  修改视图
ALTER VIEW HumanResources.EmployeeHireDate  
AS  
SELECT p.FirstName, p.LastName, e.HireDate  
FROM HumanResources.Employee AS e JOIN Person.Person AS  p  
ON e.BusinessEntityID = p.BusinessEntityID  
WHERE HireDate < CONVERT(DATETIME,'20020101',101) ;   
GO

4.通过视图修改数据

这里先给出视图定义

CREATE VIEW [HumanResources].[vEmployeeDepartmentHistory] 
AS 
SELECT 
    e.[BusinessEntityID] 
    ,p.[Title] 
    ,p.[FirstName] 
    ,p.[MiddleName] 
    ,p.[LastName] 
    ,p.[Suffix] 
    ,s.[Name] AS [Shift]
    ,d.[Name] AS [Department] 
    ,d.[GroupName] 
    ,edh.[StartDate] 
    ,edh.[EndDate]
FROM [HumanResources].[Employee] e
    INNER JOIN [Person].[Person] p
    ON p.[BusinessEntityID] = e.[BusinessEntityID]
    INNER JOIN [HumanResources].[EmployeeDepartmentHistory] edh 
    ON e.[BusinessEntityID] = edh.[BusinessEntityID] 
    INNER JOIN [HumanResources].[Department] d 
    ON edh.[DepartmentID] = d.[DepartmentID] 
    INNER JOIN [HumanResources].[Shift] s
    ON s.[ShiftID] = edh.[ShiftID];

a. 通过视图更新数据

USE AdventureWorks2012 ;   
GO  
UPDATE HumanResources.vEmployeeDepartmentHistory  
SET StartDate = '20110203', EndDate = GETDATE()   
WHERE LastName = N'Smith' AND FirstName = 'Samantha';   
GO

执行前的状态

 执行后的状态

 此视图从两个表返回值。 此语句会成功,因为修改的列都来自一个基表。

b. 通过视图插入表数据

USE AdventureWorks2012 ;  
GO  
INSERT INTO HumanResources.vEmployeeDepartmentHistory (Department, GroupName)   
VALUES ('MyDepartment', 'MyGroup');   
GO

执行前

 执行后

 5.获取信息(视图的定义和属性)

a.获取视图的定义和属性

USE AdventureWorks2012;  
GO  
SELECT definition, uses_ansi_nulls, uses_quoted_identifier, is_schema_bound  
FROM sys.sql_modules  
WHERE object_id = OBJECT_ID('HumanResources.vEmployee');   
GO
USE AdventureWorks2012;   
GO  
SELECT OBJECT_DEFINITION (OBJECT_ID('HumanResources.vEmployee')) AS ObjectDefinition;   
GO
EXEC sp_helptext 'HumanResources.vEmployee';  

 b.获取视图的依赖关系

USE AdventureWorks2012;  
GO  
SELECT OBJECT_NAME(referencing_id) AS referencing_entity_name,   
    o.type_desc AS referencing_desciption,   
    COALESCE(COL_NAME(referencing_id, referencing_minor_id), '(n/a)') AS referencing_minor_id,   
    referencing_class_desc, referenced_class_desc,  
    referenced_server_name, referenced_database_name, referenced_schema_name,  
    referenced_entity_name,   
    COALESCE(COL_NAME(referenced_id, referenced_minor_id), '(n/a)') AS referenced_column_name,  
    is_caller_dependent, is_ambiguous  
FROM sys.sql_expression_dependencies AS sed  
INNER JOIN sys.objects AS o ON sed.referencing_id = o.object_id  
WHERE referencing_id = OBJECT_ID(N'Production.vProductAndDescription');  
GO

6.重命名视图

可以使用sp_rename,但是建议删除现有视图,然后使用新名称重新创建。

7.删除视图

USE AdventureWorks2012 ;  
GO  
IF OBJECT_ID ('HumanResources.EmployeeHireDate', 'V') IS NOT NULL  
DROP VIEW HumanResources.EmployeeHireDate;  
GO

参考网址

posted @ 2020-04-25 11:28  Vincent-yuan  阅读(127)  评论(0编辑  收藏  举报