mqzlp 发表于 2018-10-23 09:16:28

5. SQL -- 视图

  视图是可视化的表。
SQL CREATE VIEW 语句
什么是视图?
  在 SQL 中,视图是基于 SQL 语句的结果集的可视化的表。
  视图包含行和列,就像一个真实的表。视图中的字段就是来自一个或多个数据库中的真实的表中的字段。我们可以向视图添加 SQL 函数、WHERE 以及 JOIN 语句,我们也可以提交数据,就像这些来自于某个单一的表。
  注释:数据库的设计和结构不会受到视图中的函数、where 或 join 语句的影响。
  视图是一个虚拟表,可以用来反映一个或多个表的子集,其内容由一个查询语句定义
  是一个数据库的数据对象,并不存储数据,只是存储了一个查询语句
  被视图引用的表称为基表
  视图中的数据都来自于基表
  视图定义好后,就可以象普通表格一样使用
  使用视图实际就是执行一个保存在视图中的查询语句
SQL CREATE VIEW 语法
CREATE VIEW view_name AS  
SELECT column_name(s)
  
FROM table_name
  
WHERE condition
  注释:视图总是显示最近的数据。每当用户查询视图时,数据库引擎通过使用 SQL 语句来重建数据。
SQL CREATE VIEW 实例
  可以从某个查询内部、某个存储过程内部,或者从另一个视图内部来使用视图。通过向视图添加函数、join 等等,我们可以向用户精确地提交我们希望提交的数据。
  样本数据库 Northwind 拥有一些被默认安装的视图。视图 "Current Product List"会从 Products 表列出所有正在使用的产品。这个视图使用下列 SQL 创建:
CREATE VIEW ASSELECT ProductID,ProductNameFROM ProductsWHERE Discontinued=No  我们可以查询上面这个视图:
SELECT * FROM   Northwind 样本数据库的另一个视图会选取 Products 表中所有单位价格高于平均单位价格的产品:
CREATE VIEW ASSELECT ProductName,UnitPriceFROM ProductsWHERE UnitPrice>(SELECT AVG(UnitPrice) FROM Products)  我们可以像这样查询上面这个视图:
SELECT * FROM   另一个来自 Northwind 数据库的视图实例会计算在 1997 年每个种类的销售总数。请注意,这个视图会从另一个名为 "Product Sales for 1997" 的视图那里选取数据:
CREATE VIEW ASSELECT DISTINCT CategoryName,Sum(ProductSales) AS CategorySalesFROM GROUP BY CategoryName  我们可以像这样查询上面这个视图:
SELECT * FROM   我们也可以向查询添加条件。现在,我们仅仅需要查看 "Beverages" 类的全部销量:
SELECT * FROM WHERE CategoryName='Beverages'  创建视图语法:
  create view 视图名
  
  as select 语句
  with encryption:给视图定义文本加密
  创建一个视图同时给视图加密:
  A、从表timerecords 中,查找出clock_id,emp_id,card_id,sign_time 字段创建视图
  create view v_timeview
  as select clock_id,emp_id,sign_time
  from timerecords
  一般视图命名使用v_开头
  查询视图:
  select * from v_timeview
  查看视图详情:
  sp_help v_timeview
  查看视图文件结构:
  sp_helptext v_timeview
  若加密后,不能使用sp_helptext 看到
  B、创建一个加密的视图:
  create view v_timerecords
  with encryption
  as select clock_id,emp_id,card_id,sign_time
  from timeRecords

SQL 更新视图
  您可以使用下面的语法来更新视图:
CREATE OR REPLACE VIEW view_name AS  
SELECT column_name(s)
  
FROM table_name
  
WHERE condition
  现在,我们希望向 "Current Product List" 视图添加 "Category" 列。我们将通过下列 SQL 更新视图:
CREATE VIEW AS  
SELECT ProductID,ProductName,Category
  
FROM Products
  
WHERE Discontinued=No
SQL 撤销视图
  您可以通过 DROP VIEW 命令来删除视图。
DROP VIEW view_name  管理视图:
  A、修改视图alter view
  alter view v_timeview
  with encryption
  as select clock_id,emp_id,sign_time
  from timerecords
  B、删除视图drop view
  if exists (select 1 from sys.objects
  where object_id = object_id('v_timerecords') and TYPE = 'v')
  print 'exists'
  else print 'not exists'
  go
  drop veiw v_timerecords
  以上语句使用if exists 判断视图v_timerecords 是否存在,若存在,删除视图
  查询系统对像中的所有视图:
  select * from sys.objects
  where TYPE = 'v'
  创建视图的原则:
  只能在当前数据库中创建视图
  视图名称应与表名近似,但不得相同
  视图名称应遵循标识符的命名规则
  可以基于其他视图建立视图,最多允许嵌套32 级
  不能在视图上建立规则、默认、AFTER 触发器和全文索引
  不能创建临时视图
  一个视图最多只能包含1024 列
  创建视图时不能使用临时表。
  即使表被删除,视图定义仍将保留。
  定义视图的查询不能包含以下语句:
  ORDER BY
  COMPUTE 子句
  COMPUTE BY 子句
  INTO 关键字
  DEMO:创建一个临时视图:
  create view #view
  as
  select clock_id,emp_id,SIGN_time
  from timerecords
  返回结果:
  消息4103,级别15,状态1,第2 行
  "#view":不允许使用临时视图。
  通过视图修改数据:
  满足下列条件时,可以使用视图修改表中的数据:
  视图定义的FROM 子句中应至少包含一个表。
  选择列表中没有使用聚合函数或GROUP BY、UNION、DISTINCT 或TOP 子句。
  视图的选择列表中不包含派生列。派生列:查询的列不是来源于基表,而是另一个查询结果根据视图修改数据:
  select *
  --updatev_timerecords set emp_id = 'abc'
  from v_timerecords
  where ISNULL(emp_id,'')=''
  视图架构:
  多表视图:基于多表视图,在更新时,只能更新一个表需分开更新单个表内容
  A、创建多表视图:
  --创建student表备用
  create table student
  (
  sid varchar(20) primary key,
  cname varchar(20),
  )
  go
  --创建course表备用
  create table course
  (
  sid varchar(20) ,
  courseid int ,
  iscore numeric(5,2)
  )
  go
  --在表中插入数据备用
  insert into student values('A1001','john')
  insert into student values('A1002','marry')
  insert into student values('A1003','linda')
  insert into course values('A1001',1001,62)
  insert into course values('A1001',1005,72)
  insert into course values('A1003',1005,96)
  --创建视图,以student和course为基表
  create view v_wstudentscore
  As
  select a.sid,a.cname,b.courseid,b.iscore
  from student a inner join course b
  on a.sid=b.sid
  --*注意:inner join 类似于,on 类似于where
  --**更新视图,更新来自于基表student的name字段和来自于course表的iscore字段的值
  Update v_wstudentscore
  set cname='martin',iscore=iscore+5
  Where sid='A0001'
  返回结果:
  消息4405,级别16,状态1,第1 行
  视图或函数'v_wstudentscore' 不可更新,因为修改会影响多个基表。
  若仅更新单个表的单列:
  Update v_wstudentscore
  --setcname='martin'
  set iscore=iscore+5
  Where sid='A1001'
  返回结果:
  (2 行受影响)
  --创建一个视图,汇总emp_id的每日打卡次数
  create view v_sign_cnt
  with encryption
  as
  select CONVERT(varchar(10),SIGN_TIME,121) as sign_time
  ,emp_id
  ,COUNT(sign_time) as cnt
  from TimeRecords
  group by CONVERT (varchar(10),sign_time,121),
  emp_id
  go
  /*当需要查询每个员工的打卡次数时,就不用再写转换函数,统计函数
  可直接从视图中查询,查询速度较平时会快. */
  --查询emp_id=P1106077 的每日打卡次数
  select * from v_sign_cnt
  where emp_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
  from Demo_DB.dbo.employee
  --从demo_db中导入表timerecords
  select * into timerecords
  from Demo_DB.dbo.TimeRecords
  --创建视图
  create view v_sign
  with encryption
  as
  select a.emp_id,a.emp_name,b.clock_id,b.sign_time
  from employee a,timerecords b
  where a.emp_id = b.emp_id
  select * from v_sign
  --DEMO2:更新视图,修改其中一个工号对应的姓名为bcy
  update v_sign
  set emp_name = 'bcy'
  where emp_id = 'P1102666'
  --demo3:修改其中一个打卡时间
  update v_sign
  set sign_time = '2011-06-13 14:00:00'
  where emp_id = 'P1102666'
  and sign_time = '2011-06-13 12:56:14.000'
  --DEMO4:同时对两张表数据进行更新:
  update v_sign
  set emp_id = 'abc',clock_id = '101'
  where emp_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、创建数据库,表及约束
  create database db1
  go
  use db1
  go
  Create table customers (
  Customerid varchar(5) not null,
  CompanyName varchar(50) not null,
  ContactName varchar(30) null
  CONSTRAINT PK_customers PRIMARY KEY CLUSTERED (Customerid),
  CONSTRAINT CK_customerid CHECK (Customerid between 'AAAAA' and 'LZZZZ')
  )
  create database db2
  go
  use db2
  go
  Create table customers (
  Customerid varchar(5) not null,
  CompanyName varchar(50) not null,
  ContactName varchar(30) null,
  CONSTRAINT PK_customers PRIMARY KEY CLUSTERED (Customerid),
  CONSTRAINT CK_customerid CHECK (Customerid between 'M' and 'ZZZZZ')
  )
  go
  --2、创建视图:
  use db1
  go
  create view v_customers as
  select * from customers
  union all
  select * from db2.dbo.customers
  use db2
  go
  create view v_customers as
  select * from db1.dbo.customers
  union all
  select * from customers
  --写入记录:
  INSERT INTO v_customers VALUES('AAMAY','FUZHOU COMPANY','MARRY')
  INSERT INTO v_customers VALUES('CJOHN','XIMEN COMPANY','MARRY')
  INSERT INTO v_customers VALUES('SMITH','SHANGHAI COMPANY','TOM')
  INSERT INTO v_customers VALUES('YOUNG','FUJIAN COMPANY','JANE')
  INSERT INTO v_customers VALUES('GTOPP','BEJING COMPANY','TOM')
  INSERT INTO v_customers VALUES('QUILH','BEJING COMPANY','TOM')
  select * from v_customers
  --查看记录存储:
  use db1
  go
  select * from customers
  use db2
  go
  select * from customers
  分区视图用于多个服务器实例,将数据分散存放在2台服务器上


页: [1]
查看完整版本: 5. SQL -- 视图