作者:老王

MySQL中 视图的语法是这样的:

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]



视图对程序会产生一定的影响:

比如,以前我们会直接在数据库表上进行CRUD操作,但是这种做法相当“硬”,之所以这么说,是因为一旦数据库发生某种变化,比如说字段改名,对程序代码的影响是很大的。有了视图以后,每当建立一个新的数据库表之后,我们可以原封不动的建立一个新的数据库视图,CRUD操作均在此视图上完成,避免直接操作数据库表,如此一来,视图成为了表的facade,变化可以在视图里完成平滑的过渡,从而避免了对程序的影响。

如果你没太看懂我上面的话,不妨跟着我下面的步骤实战一下:

我们的系统有一个文章表:

CREATE TABLE article_table ( 

id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY , 

title VARCHAR(255) NOT NULL , 

content TEXT NOT NULL 

)



我们原封不动映射了一个视图:

CREATE VIEW article_view AS SELECT id, title, content 

FROM article_table



现在你可以在视图里进行CRUD操作了,一切都很顺利,不过突然有一天,因为某种原因,你不得不把字段title改名为name:

ALTER TABLE article_table CHANGE title name VARCHAR(255) NOT NULL


改名很简单,但是我们程序里的代码可能都是按title这个名字来写的,如果改名程序肯定会挂!还好我们可以重建视图来屏蔽影响:

CREATE VIEW article_view (id, title, content) AS SELECT id, name, content 

FROM article_table



也可以这样:

CREATE VIEW article_view AS SELECT id, name AS title, content 

FROM article_table



对程序而言,一切都没有改变。当然,如果原始数据库表的变化过于剧烈,视图也是爱莫能助,那时就不得不修改程序了。

再比如,以前我们会使用关联查询来取复杂数据,有时候为了效率还不得不采用反范式的方式,通过冗余数据来降低关联查询。不过毕竟反范式是有悖于数据唯一性的,稍不留神,会引起数据错乱,有了视图以后,我们可以建立一个含有冗余数据的视图,虽然建立视图时使用的同样是关联查询,但是视图的内部机制可以保证其查询效率。

继续跟着我下面的步骤实战一下:

CREATE TABLE article_table ( 

id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY , 

category_id INT UNSIGNED NOT NULL , 

title VARCHAR(255) NOT NULL , 

content TEXT NOT NULL 

) 


CREATE TABLE `category_table` ( 

id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY , 

name VARCHAR(255) NOT NULL 

)



一个很常见的需求:查询文章的同时还要得到文章所在类别的名字,无疑要使用关联查询:

SELECT article_table.*, category_table.name as category_name 

FROM article_table LEFT JOIN category_table on article_table.category_id = category_table.id



为了避免关联查询对效率的影响,我们可能会在article_table里建立一个category_name冗余字段,算了,还是直接用视图吧:

CREATE VIEW article_view AS SELECT article_table.* , category_table.name AS category_nameFROM article_table LEFT JOIN category_table ON article_table.category_id = category_table.id



注:以上观点未严格测试,基本属于意淫范畴。