从新手到高手的蜕变:MySQL 视图进阶全攻略
一、视图是什么
视图是一种虚拟表,它并非像普通表那样实际存储数据,而是基于 SQL 查询语句定义的。视图是从一个或多个基表(实际存在的物理表)或其他视图中导出的结果集。可以将其视为一个预定义的查询,当执行针对视图的操作时,MySQL 会根据视图的定义从基表中动态检索数据。
打个比方,你从一个或者好几个真实的表,还有别的视图里按照一定规则挑数据,这些挑出来的数据就构成了视图。每次你用这个视图查数据,MySQL 就按照定义视图时写的查询语句,去真实的表里现找数据给你。
二、主要用途
数据抽象与简化:通过视图可以将复杂的 SQL 查询封装起来,为用户提供一个简单的接口。用户无需了解基表的具体结构和复杂的查询逻辑,只需对视图进行操作即可获取所需数据。
例如,当基表包含多个列和复杂的关联关系时,可创建一个只包含用户所需列的视图,简化数据访问。
数据安全:可以通过视图限制用户对基表数据的访问权限。只向用户提供视图,而不给予基表的直接访问权限,从而控制用户能够看到和操作的数据范围。
例如,对于包含敏感信息(如员工工资)的表,可以创建一个不包含敏感列的视图供普通用户访问。
逻辑数据独立性:当基表的结构发生变化时,只需相应地修改视图的定义,而不需要修改使用该视图的应用程序。这增强了数据的逻辑独立性,减少了对应用程序的影响。
三、限制与注意事项
更新限制:并非所有视图都支持更新操作(插入、更新、删除)。一般来说,只有满足一定条件的简单视图才支持更新,例如视图的 SELECT
语句中不能包含聚合函数、GROUP BY
、DISTINCT
等。
性能影响:虽然视图可以简化查询,但如果视图定义复杂,包含大量的连接和子查询,可能会影响查询性能。在使用视图时,需要进行适当的性能优化。
依赖关系:视图依赖于基表,当基表被删除或结构发生重大变化时,视图可能会失效。因此,在对基表进行操作时,需要考虑对相关视图的影响。
四、创建语法
create
[or replace]
[algorithm = {undefined | merge | temptable }]
[definer = {user | current_user}]
[sql security {definer | invoker }]
view view_name [(column_list)] column_list
as select_statement
[with [cascaded | local] check option]
or replace: 这是一个组合关键字,用于创建或替换视图。如果视图 view_name 不存在,它将按照 select_statement 的内容创建一个新的视图,如果视图 view_name 已经存在,它将使用 select_statement 中的内容替换原视图的定义
algorithm:在创建或修改视图时使用,它用于指定视图的算法
undefined:默认选项,它会根据视图的定义和优化器的判断来选择最适合的算法
merge: 当对视图进行查询操作,mysql 会将视图的查询语句和外部查询语句合并成一个单一的查询语句
temptable:MySQL 会将视图的结果存储在一个临时表中。当对视图进行查询时,实际上是在查询这个临时表
definer: 指定视图的定义者,它后面跟着一个用户账号,通常以 'username'@'host' 的形式表示。它指定了在执行该视图时使用哪个用户的权限 。
sql security:在执行视图时使用谁的权限
definer:视图在执行时将使用视图创建者 definer 的权限,而不是执行该视图的用户的权限
invoker:视图在执行时将使用执行该视图的用户的权限。
view_name: 这是要创建的视图的名称
column_list: 这是一个用逗号分隔的列名列表,用于指定视图中的列名。如果提供了这个列表,那么视图中的列将使用这些列名,而不是使用 select_statement 中查询出来的列名。
with check option:当通过视图更新数据时,会检查新的数据是否满足 select_statement 中的 where 条件。如果不满足,则不允许更新
cascaded :当视图基于另一个视图时,会检查所有依赖视图的 WHERE 条件。如果有多个嵌套视图,它会从当前视图开始,检查当前视图和所有上层视图的 WHERE 条件。
local:只检查当前视图的 WHERE 条件,而不考虑依赖视图的条件。
五、使用示例
# 创建表结构
mysql> create table t (id int);
Query OK, 0 rows affected (0.02 sec)
# 插入数据
mysql> insert into t select 1;
Query OK, 1 row affected (0.00 sec)
# 创建视图
mysql> create
-> or replace
-> view t_v (ids) as
-> select * from t where id < 10;
Query OK, 0 rows affected (0.01 sec)
# 查询数据 我们发现查询返回的列是我们视图定义的,而不是基表定义的。但数据是基于基表的
mysql> select * from t_v;
+------+
| ids |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
# 根据视图来插入数据,当我们插入大于范围的数据 没有发生异常,数据也没有插入成功
mysql> insert into t_v select 20 ;
Query OK, 1 row affected (0.00 sec)
mysql> select * from t_v;
+------+
| ids |
+------+
| 1 |
+------+
# 修改视图定义,开启检查插入数据的范围
mysql> create
-> or replace
-> view t_v (ids) as
-> select * from t where id < 10
-> with check option;
Query OK, 0 rows affected (0.01 sec)
# 我们发现,当插入数据超出范围,会返回异常提示
mysql> insert into t_v select 20;
ERROR 1369 (HY000): CHECK OPTION failed 'innodb_test.t_v'