mysql视图之创建视图(CREATE VIEW)和使用限制实例详解
本文实例讲述了mysql视图之创建视图(CREATEVIEW)和使用限制。分享给大家供大家参考,具体如下:
mysql5.x版本之后支持数据库视图,在mysql中,视图的几乎特征符合SQL:2003标准。mysql以两种方式处理对视图的查询:
- 第一种方式,MySQL会根据视图定义语句创建一个临时表,并在此临时表上执行传入查询。
- 第二种方式,MySQL将传入查询与查询定义为一个查询并执行组合查询。
mysql支持版本系统的视图,当每次视图被更改或替换时,视图的副本将在驻留在特定数据库文件夹的arc(archive)文件夹中备份。备份文件的名称为view_name.frm-00001。如果再次更改视图,mysql将创建一个名为view_name.frm-00002的新备份文件。mysql允许基于其他视图创建视图,就是在视图定义的select语句中,可以引用另一个视图。
好啦,多的咱就不赘述了,接下来咱们尝试使用CREATEVIEW语句创建视图,先来看下语法结构:
CREATE [ALGORITHM={MERGE|TEMPTABLE|UNDEFINED}] VIEW[database_name].[view_name] AS [SELECTstatement]
然后我们来详细看下上面的sql中的各种词是什么意思。首先,第一个中括号里代表的就是创建视图是的算法属性,它允许我们控制mysql在创建视图时使用的机制,并且mysql提供了三种算法:MERGE,TEMPTABLE和UNDEFINED。我们来分别看下:
- 使用MERGE算法,mysql首先将输入查询与定义视图的select语句组合成单个查询。然后mysql执行组合查询返回结果集。如果select语句包含集合函数(如min,max,sum,count,avg等)或distinct,groupby,havaing,limit,union,unionall,子查询,则不允许使用MERGE算法。如果select语句无引用表,则也不允许使用MERGE算法。如果不允许MERGE算法,mysql将算法更改为UNDEFINED。我们要注意,将视图定义中的输入查询和查询组合成一个查询称为视图分辨率。
- 使用TEMPTABLE算法,mysql首先根据定义视图的SELECT语句创建一个临时表,然后针对该临时表执行输入查询。因为mysql必须创建临时表来存储结果集并将数据从基表移动到临时表,所以TEMPTABLE算法的效率比MERGE算法效率低。另外,使用TEMPTABLE算法的视图是不可更新的。
- 当我们创建视图而不指定显式算法时,UNDEFINED是默认算法。UNDEFINED算法使mysql可以选择使用MERGE或TEMPTABLE算法。mysql优先使用MERGE算法进行TEMPTABLE算法,因为MERGE算法效率更高。
然后就是view后面的词组了,它就是名称的意思,在数据库中,视图和表共享相同的命名空间,因此视图和表不能具有相同的名称。另外,视图的名称必须遵循表的命名规则。
最后就是SELECT语句了。在SELECT语句中,可以从数据库中存在的任何表或视图查询数据,同时SELECT语句必须遵循以下几个规则:
- SELECT语句可以在where语句中包含子查询,但FROM子句中的不能包含子查询。
- SELECT语句不能引用任何变量,包括局部变量,用户变量和会话变量。
- SELECT语句不能引用准备语句的参数。
在这里我们得稍稍注意下,SELECT语句不需要引用任何表。完事呢,我们来尝试基于orderDetails表来创建一个表示每个订单的总销售额的视图:
CREATEVIEWSalePerOrderAS SELECT orderNumber,SUM(quantityOrdered*priceEach)total FROM orderDetails GROUPbyorderNumber ORDERBYtotalDESC;
我们如果使用SHOWTABLES命令来查看示例数据库(yiibaidb)中的所有表,还会看到SalesPerOrder视图也显示在表的列表中:
mysql>SHOWTABLES; +--------------------+ |Tables_in_yiibaidb| +--------------------+ |article_tags| |contacts| |customers| |departments| |employees| |offices| |offices_bk| |offices_usa| |orderdetails| |orders| |payments| |productlines| |products| |saleperorder| +--------------------+ 14rowsinset
这是因为视图和表共享相同的命名空间。要知道哪个对象是视图或表,就得使用SHOWFULLTABLES命令,如下所示:
mysql>SHOWFULLTABLES; +--------------------+------------+ |Tables_in_yiibaidb|Table_type| +--------------------+------------+ |article_tags|BASETABLE| |contacts|BASETABLE| |customers|BASETABLE| |departments|BASETABLE| |employees|BASETABLE| |offices|BASETABLE| |offices_bk|BASETABLE| |offices_usa|BASETABLE| |orderdetails|BASETABLE| |orders|BASETABLE| |payments|BASETABLE| |productlines|BASETABLE| |products|BASETABLE| |saleperorder|VIEW| +--------------------+------------+ 14rowsinset
结果集中的table_type列指定哪个对象是视图,哪个对象是一个表(基表)。如上所示,saleperorder对应table_type列的值为:VIEW。然而,如果要查询每个销售订单的总销售额,只需要对SalePerOrder视图执行一个简单的SELECT语句,如下所示:
SELECT * FROM salePerOrder;
执行上面查询语句,得到以下结果:
+-------------+----------+ |orderNumber|total| +-------------+----------+ |10165|67392.85| |10287|61402.00| |10310|61234.67| |10212|59830.55| |--此处省略了manymany数据--| |10116|1627.56| |10158|1491.38| |10144|1128.20| |10408|615.45| +-------------+----------+ 327rowsinset
我们再来基于另一个视图创建一个视图,比如,根据SalesPerOrder视图创建名为大销售订单(BigSalesOrder)的视图,以显示总计大于60,000的每个销售订单,如下所示:
CREATEVIEWBigSalesOrderAS SELECT orderNumber,ROUND(total,2)astotal FROM saleperorder WHERE total>60000;
现在,我们可以从BigSalesOrder视图查询数据,如下所示:
SELECT orderNumber,total FROM BigSalesOrder;
执行上面查询语句,得到以下结果:
+-------------+----------+ |orderNumber|total| +-------------+----------+ |10165|67392.85| |10287|61402.00| |10310|61234.67| +-------------+----------+ 3rowsinset
完事我们再来尝试使用innerjoin创建包含客户编号和客户支付的总金额的视图,如下所示:
CREATEVIEWcustomerOrdersAS SELECT c.customerNumber, p.amount FROM customersc INNERJOIN paymentspONp.customerNumber=c.customerNumber GROUPBYc.customerNumber ORDERBYp.amountDESC;
我们使用下面的sql来查询customerOrders视图中的数据:
+----------------+-----------+ |customerNumber|amount| +----------------+-----------+ |124|101244.59| |321|85559.12| |239|80375.24| |****此处省略了manymany数据***| |219|3452.75| |216|3101.4| |161|2434.25| |172|1960.8| +----------------+-----------+ 98rowsinset
再来尝试使用子查询创建包含价格高于所有产品的平均价格的产品的视图,如下所示:
CREATEVIEWaboveAvgProductsAS SELECT productCode,productName,buyPrice FROM products WHERE buyPrice> (SELECT AVG(buyPrice) FROM products) ORDERBYbuyPriceDESC;
我们来查询aboveAvgProducts视图的数据:
SELECT * FROM aboveAvgProducts;
执行上面查询语句,得到以下结果:
+-------------+-----------------------------------------+----------+ |productCode|productName|buyPrice| +-------------+-----------------------------------------+----------+ |S10_4962|1962LanciaADelta16V|103.42| |S18_2238|1998ChryslerPlymouthProwler|101.51| |S10_1949|1952AlpineRenault1300|98.58| |*************此处省略了manymany数据*********************************| |S18_3320|1917MaxwellTouringCar|57.54| |S24_4258|1936ChryslerAirflow|57.46| |S18_3233|1985ToyotaSupra|57.01| |S18_2870|1999Indy500MonteCarloSS|56.76| |S32_4485|1974Ducati350Mk3Desmo|56.13| |S12_4473|1957ChevyPickup|55.7| |S700_3167|F/A18Hornet1/72|54.4| +-------------+-----------------------------------------+----------+ 54rowsinset
好啦,到这里了,视图的创建和使用已经介绍的差不多了。但是,视图就没有什么使用的限制么?答案当然是有的,我们来分别看下。
首先,我们不能在视图上创建索引,再来就是当使用合并算法的视图查询数据时,mysql会使用底层表的索引,还有就是对于使用诱惑算法的视图,当我们针对视图查询数据时,不会使用索引。
还有就是要注意在mysql5.7.7之前版本,是不能在SELECT语句的FROM子句中使用子查询来定义视图的。
再来就是如果删除或重命名视图所基于的表,则mysql不会发出任何错误。但是,mysql会使视图无效,我们可以使用CHECKTABLE语句来检查视图是否有效。
一个简单的视图可以更新表中数据,但是基于具有连接,子查询等的复杂select语句创建的视图无法更新。
mysql不像Oracle、PostgreSQL等其他数据库系统那样支持物理视图,mysql是不支持物理视图的。
好啦,关于视图本次就记录到这里了。
更多关于MySQL相关内容感兴趣的读者可查看本站专题:《MySQL查询技巧大全》、《MySQL事务操作技巧汇总》、《MySQL存储过程技巧大全》、《MySQL数据库锁相关技巧汇总》及《MySQL常用函数大汇总》
希望本文所述对大家MySQL数据库计有所帮助。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。