15. MySQL视图
视图并不在数据库中实际存在, 行和列数据来自定义视图的查询中使用的表, 并且是在使用视图时动态生成的。
优点:
- 简单: 使用视图的用户完全不需要关心后面对应的表的结构、 关联条件和筛选条件,对用户来说已经是过滤好的复合条件的结果集。
- 安全: 使用视图的用户只能访问他们被允许查询的结果集; 对表的权限管理并不能限制到某个行某个列,但是通过视图就可以简单的实现。
- 数据独立: 一旦视图的结构确定了, 可以屏蔽表结构变化对用户的影响, 源表增加列对视图没有影响; 源表修改列名, 则可以通过修改视图来解决, 不会造成对访问者的影响。
1. 创建或者修改视图⚓
创建视图需要有 CREATE VIEW
的权限,并且对于查询涉及的列有 SELECT
权限。如果使用
CREATE OR REPLACE
或者 ALTER
修改视图,那么还需要该视图的 DROP
权限。
CREATE
[OR REPLACE]
[ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
[DEFINER = { user | CURRENT_USER }]
[SQL SECURITY { DEFINER | INVOKER }]
VIEW view_name [(column_list)]
AS select_statement
[WITH [CASCADED | LOCAL] CHECK OPTION]
CREATE OR REPLACE VIEW:
- 视图不存在:和 CREATE VIEW 等价
- 视图存在:和 ALTER VIEW 等价
1.1 MySQL 创建视图的限制⚓
MySQL 定义视图的限制:
- SELECT 语句中的 FROM 语法中不能包含子查询
- SELECT 语句不能引用系统变量或用户定义的变量
- 在存储过程中,SELECT 不能引用程序参数或局部变量
- SELECT 语句不能引用准备好的声明参数(statement parameters)???
- 在定义中引用的表或视图必须存在。
- 不能引用临时表,所以不能创建临时视图
- 不能讲视图与触发器关联起来
- SELECT 子句中列的别名最大长度为64个字符
- 不能在视图中创建索引
对于第一条,如果视图是从其他数据库迁移过来的, 那么可能需要因此做一些改动, 可以将子查询的内容先定义成一个视图,然后对该视图再创建视图就可以实现类似的功能了。
1.2 MySQL 更新视图的限制⚓
视图的可更新性(即通过视图进行插入等操作)和视图中查询的定义有关系,以下类型的视图是不可更新的:
-
包含以下关键字的 SQL 语句: 聚合函数 (SUM、 MIN、 MAX、 COUNT 等)、 DISTINCT、 GROUP BY、HAVING、UNION 或者 UNION ALL。
-
常量视图。
- SELECT 中包含子查询。
- JION。
- FROM 一个不能更新的视图。
- WHERE 子句的子查询引用了 FROM 子句中的表。
WITH [CASCADED | LOCAL] CHECK OPTION
决定了是否允许更新不满足视图条件的记录。
- CASCADED:必须满足针对该视图的所有条件才可以更新。
- LOCAL:只要满足本视图的条件就可以更新。
- 如果不指定此选项,与LOCAL规则相同,但不满足本视图条件时会显示成功且不会更新数据。
/* 基础视图 */
MariaDB [MYISAM_TEST]> CREATE OR REPLACE VIEW PARENT_VIEW (PID, PNAME) AS SELECT * FROM PARENT WHERE ID < 5;
/* 二层视图,CASCADED */
MariaDB [MYISAM_TEST]> CREATE OR REPLACE VIEW PARENT_VIEW1(PID, PNAME) AS SELECT * FROM PARENT_VIEW WHERE PID > 1 WITH CASCADED CHECK OPTION;
/* 插入失败 */
MariaDB [MYISAM_TEST]> INSERT INTO PARENT_VIEW1 VALUES(11, 'DSAF');
ERROR 1369 (HY000): CHECK OPTION failed 'MYISAM_TEST.PARENT_VIEW1'
/* 二层视图,LOCAL */
MariaDB [MYISAM_TEST]> CREATE OR REPLACE VIEW PARENT_VIEW1(PID, PNAME) AS SELECT * FROM PARENT_VIEW WHERE PID > 1 WITH LOCA CHECK OPTION;
/* 插入成功 */
MariaDB [MYISAM_TEST]> INSERT INTO PARENT_VIEW2 VALUES(11, 'DSAF');
Query OK, 1 row affected (0.01 sec)
/* 二层视图,不指定检查选项 */
MariaDB [MYISAM_TEST]> CREATE OR REPLACE VIEW PARENT_VIEW3(PID, PNAME) AS SELECT * FROM PARENT_VIEW WHERE PID > 2;
/* 不会报错,也不会更新 */
MariaDB [MYISAM_TEST]> DELETE FROM PARENT_VIEW3 WHERE PID=1;
Query OK, 0 rows affected (0.00 sec)
2. 查看视图⚓
SHOW TABLES;
SHOW TABLE STATUS;
SHOW CREATE VIEW;
3. 删除视图⚓
一次可以删除多个视图
DROP VIEW [IF EXISTS]
view_name [, view_name] ...
[RESTRICT | CASCADE]