视图是可视化的表。
在 SQL 中,视图是基于 SQL 语句的结果集的可视化的表。
视图包含行和列,就像一个真实的表。视图中的字段就是来自一个或多个数据库中的真实的表中的字段。我们可以向视图添加 SQL 函数、WHERE 以及 JOIN 语句,我们也可以提交数据,就像这些来自于某个单一的表。
注释:数据库的设计和结构不会受到视图中的函数、where 或 join 语句的影响。
视图是一个虚拟表,可以用来反映一个或多个表的子集,其内容由一个查询语句定义
是一个数据库的数据对象,并不存储数据,只是存储了一个查询语句
被视图引用的表称为基表
视图中的数据都来自于基表
视图定义好后,就可以象普通表格一样使用
使用视图实际就是执行一个保存在视图中的查询语句
CREATE VIEW view_name AS SELECT column_name(s) FROM table_name WHERE condition
注释:视图总是显示最近的数据。每当用户查询视图时,数据库引擎通过使用 SQL 语句来重建数据。
可以从某个查询内部、某个存储过程内部,或者从另一个视图内部来使用视图。通过向视图添加函数、join 等等,我们可以向用户精确地提交我们希望提交的数据。
样本数据库 Northwind 拥有一些被默认安装的视图。视图 "Current Product List" 会从 Products 表列出所有正在使用的产品。这个视图使用下列 SQL 创建:
CREATE VIEW [Current Product List] ASSELECT ProductID,ProductNameFROM ProductsWHERE Discontinued=No
我们可以查询上面这个视图:
SELECT * FROM [Current Product List]
Northwind 样本数据库的另一个视图会选取 Products 表中所有单位价格高于平均单位价格的产品:
CREATE VIEW [Products Above Average Price] ASSELECT ProductName,UnitPriceFROM ProductsWHERE UnitPrice>(SELECT AVG(UnitPrice) FROM Products)
我们可以像这样查询上面这个视图:
SELECT * FROM [Products Above Average Price]
另一个来自 Northwind 数据库的视图实例会计算在 1997 年每个种类的销售总数。请注意,这个视图会从另一个名为 "Product Sales for 1997" 的视图那里选取数据:
CREATE VIEW [Category Sales For 1997] ASSELECT DISTINCT CategoryName,Sum(ProductSales) AS CategorySalesFROM [Product Sales for 1997]GROUP BY CategoryName
我们可以像这样查询上面这个视图:
SELECT * FROM [Category Sales For 1997]
我们也可以向查询添加条件。现在,我们仅仅需要查看 "Beverages" 类的全部销量:
SELECT * FROM [Category Sales For 1997]WHERE CategoryName='Beverages'
创建视图语法:
create view 视图名
[With encryption ]
as select 语句
with encryption:给视图定义文本加密
创建一个视图同时给视图加密:
A、从表timerecords 中,查找出clock_id,emp_id,card_id,sign_time 字段创建视图
createview v_timeview
asselect clock_id,emp_id,sign_time
fromtimerecords
一般视图命名使用v_开头
查询视图:
select* from v_timeview
查看视图详情:
sp_helpv_timeview
查看视图文件结构:
sp_helptextv_timeview
若加密后,不能使用sp_helptext 看到
B、创建一个加密的视图:
createview v_timerecords
withencryption
asselect clock_id,emp_id,card_id,sign_time
fromtimeRecords
您可以使用下面的语法来更新视图:
CREATE OR REPLACE VIEW view_name AS SELECT column_name(s) FROM table_name WHERE condition
现在,我们希望向 "Current Product List" 视图添加 "Category" 列。我们将通过下列 SQL 更新视图:
CREATE VIEW [Current Product List] AS SELECT ProductID,ProductName,Category FROM Products WHERE Discontinued=No
您可以通过 DROP VIEW 命令来删除视图。
DROP VIEW view_name
管理视图:
A、修改视图alter view
alterview v_timeview
withencryption
asselect clock_id,emp_id,sign_time
fromtimerecords
B、删除视图drop view
if exists (select 1 from sys.objects
whereobject_id = object_id('v_timerecords') and TYPE = 'v')
print'exists'
elseprint 'not exists'
go
dropveiwv_timerecords
以上语句使用if exists 判断视图v_timerecords 是否存在,若存在,删除视图
查询系统对像中的所有视图:
select* from sys.objects
whereTYPE = 'v'
创建视图的原则:
只能在当前数据库中创建视图
视图名称应与表名近似,但不得相同
视图名称应遵循标识符的命名规则
可以基于其他视图建立视图,最多允许嵌套32 级
不能在视图上建立规则、默认、AFTER 触发器和全文索引
不能创建临时视图
一个视图最多只能包含1024 列
创建视图时不能使用临时表。
即使表被删除,视图定义仍将保留。
定义视图的查询不能包含以下语句:
ORDER BY
COMPUTE 子句
COMPUTE BY 子句
INTO 关键字
DEMO:创建一个临时视图:
createview #view
as
selectclock_id,emp_id,SIGN_time
fromtimerecords
返回结果:
消息4103,级别15,状态1,第2 行
"#view":不允许使用临时视图。
通过视图修改数据:
满足下列条件时,可以使用视图修改表中的数据:
视图定义的FROM 子句中应至少包含一个表。
选择列表中没有使用聚合函数或GROUP BY、UNION、DISTINCT 或TOP 子句。
视图的选择列表中不包含派生列。派生列:查询的列不是来源于基表,而是另一个查询结果根据视图修改数据:
select*
--updatev_timerecords set emp_id = 'abc'
fromv_timerecords
whereISNULL(emp_id,'')=''
视图架构:
多表视图:基于多表视图,在更新时,只能更新一个表需分开更新单个表内容
A、创建多表视图:
--创建student表备用
createtable student
(
sidvarchar(20) primary key,
cnamevarchar(20),
)
go
--创建course表备用
createtable course
(
sidvarchar(20) ,
courseidint ,
iscorenumeric(5,2)
)
go
--在表中插入数据备用
insertinto student values('A1001','john')
insertinto student values('A1002','marry')
insertinto student values('A1003','linda')
insertinto course values('A1001',1001,62)
insertinto course values('A1001',1005,72)
insertinto course values('A1003',1005,96)
--创建视图,以student和course为基表
createview v_wstudentscore
As
selecta.sid,a.cname,b.courseid,b.iscore
fromstudent a inner join course b
on a.sid=b.sid
--*注意:inner join 类似于,on 类似于where
--**更新视图,更新来自于基表student的name字段和来自于course表的iscore字段的值
Updatev_wstudentscore
set cname='martin',iscore=iscore+5
Wheresid='A0001'
返回结果:
消息4405,级别16,状态1,第1 行
视图或函数'v_wstudentscore' 不可更新,因为修改会影响多个基表。
若仅更新单个表的单列:
Updatev_wstudentscore
--setcname='martin'
set iscore=iscore+5
Wheresid='A1001'
返回结果:
(2 行受影响)
--创建一个视图,汇总emp_id的每日打卡次数
createview v_sign_cnt
withencryption
as
selectCONVERT(varchar(10),SIGN_TIME,121) as sign_time
,emp_id
,COUNT(sign_time) as cnt
fromTimeRecords
groupby CONVERT (varchar(10),sign_time,121),
emp_id
go
/*当需要查询每个员工的打卡次数时,就不用再写转换函数,统计函数
可直接从视图中查询,查询速度较平时会快. */
--查询emp_id=P1106077 的每日打卡次数
select* from v_sign_cnt
whereemp_id = 'P1106077'
--DEMO1:
/*多表视图:timerecords eployee
取eployee中的emp_id,emp_name,
timerecords中的clock_id,sign_time
要求:eployee.emp_id=timerecords.emp_id */
--从MYDB中导入表employee
select* into employee
fromDemo_DB.dbo.employee
--从demo_db中导入表timerecords
select* into timerecords
fromDemo_DB.dbo.TimeRecords
--创建视图
createview v_sign
withencryption
as
selecta.emp_id,a.emp_name,b.clock_id,b.sign_time
fromemployee a,timerecords b
wherea.emp_id = b.emp_id
select* from v_sign
--DEMO2:更新视图,修改其中一个工号对应的姓名为bcy
updatev_sign
set emp_name = 'bcy'
whereemp_id = 'P1102666'
--demo3:修改其中一个打卡时间
updatev_sign
set sign_time = '2011-06-13 14:00:00'
whereemp_id = 'P1102666'
andsign_time = '2011-06-13 12:56:14.000'
--DEMO4:同时对两张表数据进行更新:
updatev_sign
set emp_id = 'abc',clock_id = '101'
whereemp_id = 'P1102666'
返回结果:
Msg4405, Level 16, State 1, Line 1
视图或函数 'v_sign' 不可更新,因为修改会影响多个基表。
分区视图:
分区视图允许将大型表中的数据拆分成较小的成员表。根据其中一列中的数据值范围,在各个成员表之间对数据进行分区。每个成员表的数据范围都在为分区依据列指定的CHECK 约束中定义。然后定义一个视图,以使用 UNION ALL 将选定的所有成员表组合成单个结果集。引用该视图的 SELECT 语句为分区依据列指定搜索条件后,查询优化器将使用 CHECK 约束定义确定哪个成员表包含相应行。
DEMO:DB1 及DB2 均有一张客户资料表,通过视图将2 个数据库下的客户资料进行连接要求A-L 的客户存储在DB1 下,M-Z 的客户存储在DB2 下
--1、创建数据库,表及约束
createdatabase db1
go
use db1
go
Createtable customers (
Customeridvarchar(5) not null,
CompanyNamevarchar(50) not null,
ContactNamevarchar(30) null
CONSTRAINTPK_customers PRIMARY KEY CLUSTERED (Customerid),
CONSTRAINTCK_customerid CHECK (Customerid between 'AAAAA' and 'LZZZZ')
)
createdatabase db2
go
use db2
go
Createtable customers (
Customeridvarchar(5) not null,
CompanyNamevarchar(50) not null,
ContactNamevarchar(30) null,
CONSTRAINTPK_customers PRIMARY KEY CLUSTERED (Customerid),
CONSTRAINTCK_customerid CHECK (Customerid between 'M' and 'ZZZZZ')
)
go
--2、创建视图:
use db1
go
createview v_customers as
select* from customers
unionall
select* from db2.dbo.customers
use db2
go
createview v_customers as
select* from db1.dbo.customers
unionall
select* from customers
--写入记录:
INSERTINTO v_customers VALUES('AAMAY','FUZHOU COMPANY','MARRY')
INSERTINTO v_customers VALUES('CJOHN','XIMEN COMPANY','MARRY')
INSERTINTO v_customers VALUES('SMITH','SHANGHAI COMPANY','TOM')
INSERTINTO v_customers VALUES('YOUNG','FUJIAN COMPANY','JANE')
INSERTINTO v_customers VALUES('GTOPP','BEJING COMPANY','TOM')
INSERTINTO v_customers VALUES('QUILH','BEJING COMPANY','TOM')
select* from v_customers
--查看记录存储:
use db1
go
select* from customers
use db2
go
select* from customers
分区视图用于多个服务器实例,将数据分散存放在2台服务器上