赞
踩
视图是一个虚拟表,不存放任何数据。在使用SQL语句访问视图的时候,它返回的数据是 MySQL 从表中生成的。视图和表是在同一个命名空间,MySOL 在很多地方对于视图和表是同样对待的。不过视图和表也有不同,例如,不能对视图创建触发器,也不能使用 DROP TABLE命令删除视图。
- CREATE
- [OR REPLACE]
- [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
- [DEFINER = user]
- [SQL SECURITY { DEFINER | INVOKER }]
- VIEW 视图名 [(column_list)]
- AS 查询语句
- [WITH [CASCADED | LOCAL] CHECK OPTION]
OR REPLACE
子句,该语句会替换掉已有的视图ALGORITHM
可取三个值:MERGE、TEMPTABLE或UNDEFINED。默认使用UNDEFINED,ALGORITHM
会影响MySQL处理视图的方式。[DEFINER = user]
: 可选项,指定视图的创建者。[SQL SECURITY { DEFINER | INVOKER }]
:可选项,表示该用户使用该视图时使用的角色权限,如果设置为DEFINER
,则表示使用该视图的用户必须是创建视图的用户指定的用户,并且这个指定的用户还要具有相关的权限才能使用;如果设置为INVOKER
则只要用户有相关的权限就能使用。WITH CHECK [LOCAL] OPTION
如果使用了该选项,则在对视图执行INSERT
或UPDATE
操作时,会检查新行或更新的行是否符合视图的定义,并阻止不符合条件的数据被插入或更新。LOCAL可加可不加WITH CASCADED CHECK OPTION
:如果使用了该选项,则除了执行WITH CHECK OPTION
的检查外,还会对基础表也进行相同的检查,确保视图和基础表的数据一致性。示例程序使用的数据库为官方sakila数据库
示例程序:
- CREATE
- OR REPLACE VIEW pg_rating AS SELECT
- film_id,
- title,
- rating
- FROM
- `film`
- WHERE
- rating = "PG" WITH CHECK OPTION
创建视图的规则
视图可以嵌套,即可以利用从其他视图中检索数据的查询来构造
一个视图。
ORDER BY可以用在视图中,但如果从该视图检索数据SELECT中也
含有ORDER BY,那么该视图中的ORDER BY将被覆盖。
视图不能索引,也不能有关联的触发器或默认值。
视图可以和表一起使用。例如,编写一条联结表和视图的SELECT
语句。
一般来说直接将视图作为一张表来使用即可
SELECT * FROM pg_rating WHERE film_id <50
复杂查询(一般这种查询都包含了多表的连接),
考虑到这里有一个需求,我们要根据演员的姓名来查询这个演员所参演过的电影,如果直接使用原始查询。可以使用下面的查询语句
- SELECT a.first_name,a.last_name,f.title FROM actor a
- INNER JOIN film_actor fa
- ON a.actor_id=fa.actor_id
- INNER JOIN film f
- ON fa.film_id=f.film_id
- WHERE a.first_name="ADAM" AND a.last_name="HOPPER"
如果使用视图,可以是这样的形式:
- CREATE VIEW actor_participated_film AS
- SELECT a.first_name,a.last_name,f.title FROM actor a
- INNER JOIN film_actor fa
- ON a.actor_id=fa.actor_id
- INNER JOIN film f
- ON fa.film_id=f.film_id
- SELECT * FROM actor_participated_film
- WHERE first_name="ADAM" AND last_name="HOPPER"
这里注意:我们直接使用first_name和last_name即可,不需要使用创建视图时我们为联接表创建的别名,可以把视图当作一张表,这样我们在使用视图来做查询时,直接使用视图上的列命名即可,不再需要考虑视图的构造细节
可以看出使用视图的查询逻辑上确实更加清晰
有时我们希望能修改表的显示和查询方式,但是又不希望直接修改表的结构,就可以在视图中修改表的格式。
还是上面的查询,我们认为需要分开来查询并显示first_name,last_name太过麻烦,我们希望能直接显示全名,并且在查询时能使用全名来查询:
所以我们可以使用这样的查询
- CREATE VIEW actor_participated_film_name AS
- SELECT CONCAT(a.first_name," ",a.last_name) AS name,f.title
- FROM actor a
- INNER JOIN film_actor fa
- ON a.actor_id=fa.actor_id
- INNER JOIN film f
- ON fa.film_id=f.film_id
接下来我们直接使用下面这种查询即可
- SELECT *
- FROM actor_participated_film_name
- WHERE name="ADAM HOPPER"
有时我们想要先从表中过滤掉不需要的数据,然后再进行查询。
考虑下面的应用场景:我们需要film中选择时长大于90分钟的电影作为一个分类,然后再从其中做查询:
SELECT * FROM film WHERE length<90
直接查询表的数据不符合我们的要求时,就可以使用视图来先修改表的显示数据,然后再做处理。
例如:我们需要将账单中的支付数额从美元转为人民币(当前汇率为1 美元 ≈ 7.1304 人民币),就可以使用视图来查询:
- CREATE VIEW dollar_payment AS
- SELECT
- amount * 7.1304 AS dollar_amount ,
- payment_date
- FROM
- `payment`
然后我们可以再在该视图的基础上,将美元转为英镑(1 英镑 ≈ 1.2686 美元)来显示
- SELECT
- dollar_amount * 1.2686 AS pound_amount ,
- payment_date
- FROM
- dollar_payment
如果把视图想象为一张临时表,那么可以创建下面这种"伪视图":
- CREATE TEMPORARY TABLE tmp_pg_rating AS
- SELECT film_id,title,rating FROM film WHERE rating="PG";
-
- SELECT * FROM tmp_pg_rating WHERE film_id<50;
这种方式也能完成查询
如果把使用视图的查询条件合并到创建视图的查询语句中,也可以完成查询:
SELECT film_id,title,rating FROM film WHERE rating="PG" AND film_id<50;
视图的两种实现方式MERGE、TEMPTABLE就是基于上面这两种形式来完成的,一般来说我们任务MERGE的性能会更高,mysql也会优先使用MERGE算法。当视图中包含GROUY BY、DISTINCT、任何聚合函数、UNION、子查询等,只要无法在原表记录和视图记录中建立一一映射的场景中,MySQL 都将使用临时表算法来实现视图
如何判断mysql执行查询时会使用哪种算法
EXPLAIN SELECT * FROM 视图名
如果返回的结果select_type为DERVIDE
,则说明使用了临时表算法
通常,视图是可更新的(即,可以对它们使用INSERT、UPDATE和DELETE)。更新一个视图将更新其使用的表(视图本身没有数据)。如果你对视图增加或删除行,实际上是对表增加或删除行
- UPDATE pg_rating SET title="hello world" WHERE title="ACADEMY DINOSAUR"
- > Affected rows: 1
- UPDATE pg_rating SET length=50
- > 1054 - Unknown column 'length' in 'field list'
- UPDATE pg_rating SET rating="PG-13" WHERE title="hello world"
- > 1369 - CHECK OPTION failed 'sakila.pg_rating'
基于这样的形式,我们可以通过给用户设置基于列的操作权限
GRANT [SELECT/INSERT/UPDATE/DELETE] ON 视图名 WITH 用户
DROP 视图名
SHOW CREATE VIEW 视图名
示例程序
SHOW CREATE VIEW actor_info
- SELECT TABLE_NAME
- FROM information_schema.views
- WHERE table_schema = '数据库名';
示例程序
- SELECT TABLE_NAME
- FROM information_schema.views
- WHERE table_schema = 'sakila';
可以下载pdf来查看本文档:
链接:百度网盘 请输入提取码
提取码:a1a5
链接:百度网盘 请输入提取码
提取码:a1a5
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。