在MySQL中,创建视图的完整语法如下:
CREATE [OR REPLACE] [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}] VIEW view_name [(column_list)] AS select_statement [WITH [CASCADED | LOCAL] CHECK OPTION]
其对应的语法变量信息如下:
- [OR REPLACE]
- 中括号中的
OR REPLACE
关键字是可选的。如果当前数据库中已经存在指定名称的视图时,没有该关键字,将会提示错误信息;如果使用了OR REPLACE
关键字,则当前正在创建的视图会覆盖掉原来同名的视图。 - [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
ALGORITHM
子句是可选的,它表示使用何种算法来处理视图。此外,它并不属于标准SQL的一部分,而是MySQL对标准SQL进行的功能扩展。ALGORITHM
可以设置三个值:MERGE
、TEMPTABLE
或UNDEFINED
。如果没有ALGORITHM
子句,则默认值为UNDEFINED
(未定义的)。 对于MERGE
,会将引用视图的语句的文本与视图定义合并起来,使得视图定义的某一部分取代语句的对应部分。对于
TEMPTABLE
,视图的结果将被置于临时表中,然后使用它执行语句。对于
UNDEFINED
,MySQL将选择所要使用的算法。如果可能,它倾向于MERGE
而不是TEMPTABLE
,这是因为MERGE
通常更有效,而且如果使用了临时表,视图是不可更新的。之所以提供
TEMPTABLE
选项,是因为TEMPTABLE
在创建临时表之后、并在完成语句处理之前,能够释放基表上的锁定。与MERGE
算法相比,锁定释放的速度更快,这样,使用视图的其他客户端不会被屏蔽过长时间。此外,
MERGE
算法要求视图中的行和基表中的行具有一对一的关系。如果视图包含聚合函数(SUM()
,MIN()
,MAX()
,COUNT()
等)、DISTINCT
、GROUP BY
、HAVING
、UNION
或UNION ALL
、没有基表的引用文字值(例如:SELECT ‘hello‘;
)等结构中的任何一种,将失去一对一的关系,此时必须使用临时表取而代之。- [(column_list)]
(column_list)
用于自定义视图中各个字段的名称。如果没有该命令选项,那么通过视图查询到的各个字段的名称和视图所使用到的数据表的字段名称保持一致。下面是一个常见的用于创建视图的SQL语句:CREATE OR REPLACE VIEW v_user AS SELECT id, username FROM user;
由于
user
表中的字段名称为id
和username
,因此视图v_user
中的两个字段名称也分别默认为id
和username
。现在,我们将视图v_user
中的字段名称分别自定义为uid
和uname
。CREATE OR REPLACE VIEW v_user (uid, uname) AS SELECT id, username FROM user;
- select_statement
select_statement
用于指定视图的内容定义。简而言之,这里就是用户自定义的一个SELECT语句。- [WITH [CASCADED | LOCAL] CHECK OPTION]
- 该选项中的
CASCADED
为默认值,LOCAL CHECK OPTION
用于在可更新视图中防止插入或更新行。由于此选项一般不使用,因此不再赘述,具体信息请参考MySQL官方网站上的相关信息。 - 如果在创建视图的时候制定了“WITH CHECK OPTION”,那么更新数据时不能插入或更新不符合视图限制条件的记录 一般默认加上
删除视图
在MySQL中删除视图的方法非常简单,其详细语法如下:
--删除指定名称的一个或多个视图
DROP VIEW [IF EXISTS]
view_name [, view_name2]...
其中,关键字IF EXISTS
用于防止因视图不存在而提示出错,此时,只有存在该视图才会执行删除操作。DROP VIEW
语句可以一次性删除多个视图,只需要在多个视图名称之间以英文逗号隔开即可。如果多个视图存在于不同的数据库中,不数据当前数据库的视图名称之前还必须加上db_name.
前缀。
--删除视图v_user
DROP VIEW v_user;
修改视图
请参考创建视图语法中的OR REPLACE
关键字,只要具备该关键字的视图创建语句就是修改视图的SQL语句。
查看视图
在MySQL中,show tables
不仅可以用于查看当前数据库中存在哪些数据表,同时也可以查看到当前数据库中存在哪些视图。
--执行show tables
mysql> show tables;
--以下是输出结果
+----------------+
| Tables_in_test |
+----------------+
| user |
| v_user |
+----------------+
2 rows in set (0.00 sec)
查看视图详情
查看视图详情的方法有两种,一种是和查看表详情一样使用desc 视图名
,另外一种方法是show fields from 视图名
:
>DESC 视图名;
或者
>SHOW FIELDS FROM 视图名;
不过,仅仅使用show tables
语句,在输出结果中,我们根本无法区分到底哪些才是视图哪些才是真实的数据表(当然,视图的命名我们可以统一约定以"v_"开头)。此时,我们需要使用命令show full tables
,该命令可以列出额外的table_type
列,如果对应输出行上该列的值为"VIEW",则表示这是一个视图。
--执行show full tables
mysql> show full tables;
--以下是输出结果
+----------------+------------+
| Tables_in_test | Table_type |
+----------------+------------+
| user | BASE TABLE |
| v_user | VIEW |
+----------------+------------+
2 rows in set (0.00 sec)
当我们通过上述命令找到了我们所需要的视图之后,我们可以使用如下命令查看创建该视图的详细语句:
show create view view_name
例如,我们使用该命令查看创建视图v_user
的SQL语句:
--由于该语句的输出结果较为杂乱,因此使用\G命令进行格式化输出
mysql> show create view v_user \G;
--以下是格式化的输出结果
*************************** 1. row ***************************
View: v_user
Create View: CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v_user` AS select `user`.`id` AS `uid`,`user`.`username`
AS `uname` from `user`
character_set_client: utf8
collation_connection: utf8_general_ci
1 row in set (0.00 sec)
-- ----------------------------
-- View structure for `view_user_course`
-- ----------------------------
DROP VIEW
IF EXISTS `view_user_course`;
CREATE ALGORITHM = UNDEFINED
DEFINER = `root`@`localhost`
SQL SECURITY DEFINER
VIEW `view_user_course` AS (
SELECT
`uc`.`id` AS `id`,
`u`.`name` AS `username`,
`c`.`name` AS `coursename`
FROM
(
(
`user` `u`
LEFT JOIN `user_course` `uc` ON ((`u`.`id` = `uc`.`userid`))
)
LEFT JOIN `course` `c` ON ((`uc`.`courseid` = `c`.`id`))
)
);
几点说明(MySQL中的视图在标准SQL的基础之上做了扩展):
ALGORITHM=UNDEFINED:指定视图的处理算法;
DEFINER=`root`@`localhost`:指定视图创建者;
SQL SECURITY DEFINER:指定视图查询数据时的安全验证方式;
procedure与function、trigger等创建时紧接着CREATE都有个definer可选项,该definer规定了访问该procedure等的安全控制。
一、DEFINER
如:创建procedure
说明:
上面示例指定definer为用户‘admin‘@‘localhost‘,所以任意用户A访问该PROCEDURE 时,能否成功取决于A是否有调用该PROCEDURE的权限,以及definer是否有procedure中的SELECT的权限。
二、SQL SECURITY
DEFINER默认为当前用户,也可指定其他用户。如果想通过访问者来判断是否具有访问该PROCEDURE 的权限,则可用SQL SECURITY指定。
说明:
该示例虽然指定了DEFINER ,但同时也指定了SQL SECURITY 类型为INVOKER ,SQL SECURITY 优先级高,所以安全类型为INVOKER,用户能否访问取决于用户是否有执行该PROCEDURE 的权限及该PROCEDURE 中的SELECT 权限(与select操作的表有关)。
当然,也可用SQL SECURITY 指定DEFINER:SQL SECURITY DEFINER