官方文档:https://dev.mysql.com/doc/refman/5.7/en/create-view.html

  1. CREATE
  2. [OR REPLACE]
  3. [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
  4. [DEFINER = user]
  5. [SQL SECURITY { DEFINER | INVOKER }]
  6. VIEW view_name [(column_list)]
  7. AS select_statement
  8. [WITH [CASCADED | LOCAL] CHECK OPTION]

创建视图

  1. mysql> create table test_rank(id int, score int);
  2. Query OK, 0 rows affected (0.16 sec)
  3. mysql> insert into test_rank values(1, 10), (2, 20), (3, 30), (4, 30), (5, 40), (6, 40);
  4. Query OK, 6 rows affected (0.05 sec)
  5. Records: 6 Duplicates: 0 Warnings: 0
  6. mysql> select * from test_rank;
  7. +------+-------+
  8. | id | score |
  9. +------+-------+
  10. | 1 | 10 |
  11. | 2 | 20 |
  12. | 3 | 30 |
  13. | 4 | 30 |
  14. | 5 | 40 |
  15. | 6 | 40 |
  16. +------+-------+
  17. 6 rows in set (0.00 sec)
  18. --
  19. -- 创建视图
  20. --
  21. mysql> create view view_rank as select * from test_rank; -- 针对上面的test_rank创建一个视图
  22. Query OK, 0 rows affected (0.03 sec)
  23. -- 也可以对select结果增加条件进行过滤后,再创建视图
  24. mysql> show create table test_rank\G
  25. *************************** 1. row ***************************
  26. Table: test_rank
  27. Create Table: CREATE TABLE `test_rank` ( -- 得到的是表结构
  28. `id` int(11) DEFAULT NULL,
  29. `score` int(11) DEFAULT NULL
  30. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
  31. 1 row in set (0.00 sec)
  32. mysql> show create table view_rank\G -- 他是以一张表的形式存在的,可通过show tables看到
  33. *************************** 1. row ***************************
  34. View: view_rank
  35. Create View: CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `view_rank` AS select `test_rank`.`id` AS `id`,`test_rank`.`score` AS `score` from `test_rank`
  36. -- 和真正的表不同的是,这里show出来的是视图的定义
  37. character_set_client: utf8
  38. collation_connection: utf8_general_ci
  39. 1 row in set (0.00 sec)
  40. mysql> select * from view_rank; -- 可以直接查询该视图得结果
  41. +------+-------+
  42. | id | score |
  43. +------+-------+
  44. | 1 | 10 |
  45. | 2 | 20 |
  46. | 3 | 30 |
  47. | 4 | 30 |
  48. | 5 | 40 |
  49. | 6 | 40 |
  50. +------+-------+
  51. 6 rows in set (0.00 sec)
  52. -- 视图的作用是,可以对开发人员是透明的,可以隐藏部分关键的列
  53. -- 视图在mysql是虚拟表。根据视图的定义,还是去执行定义中的select语句。
  54. -- 只开放部分列
  55. mysql> create view view_rank_1 as select id from test_rank; -- 只开放id
  56. Query OK, 0 rows affected (0.04 sec)
  57. mysql> select * from view_rank_1; -- 即使 select * ,也只能看到id列,具有隐藏原来表中部分列的功能
  58. +------+
  59. | id |
  60. +------+
  61. | 1 |
  62. | 2 |
  63. | 3 |
  64. | 4 |
  65. | 5 |
  66. | 6 |
  67. +------+
  68. 6 rows in set (0.00 sec)
  69. -- 不要取用select * from 去创建视图,因为mysql会把*逐个解析成列。
  70. -- 当原来的表结构发生变化时,视图的表结构是不会发生变化的,视图在创建的瞬间,便确定了结构。
  71. -- 比如,当你alter原来的表 增加列(add columns)时,再去查询该视图,新增加的列是不存在的。
  72. mysql> alter table test_rank add column c int default 0; -- 增加一列名字为c,默认值为0
  73. Query OK, 0 rows affected (0.30 sec)
  74. Records: 0 Duplicates: 0 Warnings: 0
  75. mysql> select * from test_rank; -- 查询原表,新的列c出现了
  76. +------+-------+------+
  77. | id | score | c |
  78. +------+-------+------+
  79. | 1 | 10 | 0 |
  80. | 2 | 20 | 0 |
  81. | 3 | 30 | 0 |
  82. | 4 | 30 | 0 |
  83. | 5 | 40 | 0 |
  84. | 6 | 40 | 0 |
  85. +------+-------+------+
  86. 6 rows in set (0.00 sec)
  87. mysql> select * from view_rank; -- 尽管view_rankselect * 创建,但当时没有列c,所以无法得到c列的值
  88. +------+-------+
  89. | id | score |
  90. +------+-------+
  91. | 1 | 10 |
  92. | 2 | 20 |
  93. | 3 | 30 |
  94. | 4 | 30 |
  95. | 5 | 40 |
  96. | 6 | 40 |
  97. +------+-------+
  98. 6 rows in set (0.00 sec)

:::warning 注意:MySQL 中的视图都是虚拟表。不像 Oracle 可以物化成真实存在的表。每次查询视图,实际上还是去查询的原来的表,只是查询的规则是在视图创建时经过定义的。 :::

视图的算法

通过 show create table 命令查看视图定义的时候,可以看到一个字段:ALGORITHM,这个是用来定义视图算法的,视图的算法(ALGORITHM)有三种方式:

  • UNDEFINED:默认方式,由 MySQL 来判断使用下面的哪种算法。
  • MERGE:每次通过物理表查询得到结果,把结果 MERGE(合并)起来返回。
  • TEMPTABLE:产生一张临时表,把数据放入临时表后,客户端再去临时表取数据(不会缓存)。

TEMPTABLE 特点:即使访问条件一样,第二次查询还是会去读取物理表中的内容,并重新生成一张临时表,并不会取缓存之前的表。(临时表是 Memory 存储引擎,默认放内存,超过配置大小放磁盘)。

当查询有一个较大的结果集时,使用 TEMPTABLE 可以快速的结束对该物理表的访问,从而可以快速释放这张物理表上占用的资源。然后客户端可以对临时表上的数据做一些耗时的操作,而不影响原来的物理表。

所以一般我们使用 UNDEFINED,由 MySQL 自己去判断。

作者:殷建卫 链接:https://www.yuque.com/yinjianwei/vyrvkf/nzk6x8 来源:殷建卫 - 架构笔记 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。