11. 视图
11.1 什么是视图
视图是一种虚拟存在的表,并不在数据库中实际存在,对用户透明,行列数据来自定义视图的查询中使用的表,并且在使用的过程中动态生成的。
视图相对于普通表的优势主要包括:
- 简单:使用视图的用户无需关心查询的数据后面对应的表结构、关联条件等。用户透明。对用户来说是已经过滤好的符合条件的结果集。
- 安全:使用视图的用户只能访问他们被允许查询的结果集。
- 数据独立:对原表增加列并不会影响视图,原表修改列名,可以通过修改视图来修改结构,不会造成对访问者的影响。
11.2 视图操作
11.2.1 创建或者修改视图
创建视图的语法:
create [or replace][algorithm={undefined|merge|temptable}]
view view_name [(column_list)]
as select_statement
[with [cascaded|local] check option];
修改视图的语法:
alter [or replace][algorithm={undefined|merge|temptable}]
view view_name [(column_list)]
as select_statement
[with [cascaded|local] check option];
新增员工表和地址表,地址表的address_id是员工表的外键。
CREATE TABLE "address" (
"address_id" int(11) NOT NULL,
"address" varchar(100) DEFAULT NULL,
PRIMARY KEY ("address_id")
);
CREATE TABLE "staff" (
"staff_id" int(11) NOT NULL AUTO_INCREMENT,
"address_id" int(11) DEFAULT NULL,
"first_name" varchar(20) DEFAULT NULL,
"last_name" varchar(20) DEFAULT NULL,
PRIMARY KEY ("staff_id"),
KEY "address_id" ("address_id"),
CONSTRAINT "staff_ibfk_1" FOREIGN KEY ("address_id") REFERENCES "address" ("address_id")
);
# 创建视图
create or replace view staff_list_view
as
select s.staff_id,s.first_name,s.last_name,a.address
from staff as s, address a
where s.address_id = a.address_id;
视图的可更新性和视图中查询的定义有关系,以下类型的视图是不可更新的。
- 包含以下关键字的 SQL 语句:聚合函数(SUM、MIN、MAX、COUNT 等)、DISTINCT、GROUP BY、HAVING、UNION 或者 UNION ALL。
- 常量视图。
- SELECT 中包含子查询。
- JOIN。
- FROM 一个不能更新的视图。
- WHERE 字句的子查询引用了 FROM 字句中的表
WITH [CASCADED | LOCAL] CHECK OPTION
决定了是否允许更新数据使记录不再满足视图的条
件。这个选项与 Oracle 数据库中的选项是类似的,其中:
- LOCAL 是只要满足本视图的条件就可以更新;
- CASCADED 则是必须满足所有针对该视图的所有视图的条件才可以更新。
如果没有明确是 LOCAL 还是 CASCADED,则默认是 CASCADED。
create or replace view payment_view as
select payment_id,amount from payment
where amount < 10 WITH CHECK OPTION;
create or replace view payment_view1 as
select payment_id,amount from payment_view
where amount > 5 WITH LOCAL CHECK OPTION;
create or replace view payment_view2 as
select payment_id,amount from payment_view
where amount > 5 WITH CASCADED CHECK OPTION;
# 按书中来说,下面应该更新成功
update payment_view1 set amount=11
where payment_id = 1;
# 这句应该更新失败
update payment_view2 set amount=11
where payment_id = 1;
实际在MySQL5.6测试时,建立在payment_view上面的两层视图,无论哪个都是都是失败的!
11.2.2 删除视图
drop view [if exists] view_name [, view_name] ... [restrict | cascade];
11.2.3 查看视图
show create view view_name