在数据库中如何使用视图

1视图

视图是虚拟的表。与包含数据的表不一样,视图只包含使用动态检索数据的查询。

用实例说话:
输入

SELECT cust_name,cust_contact
FROM Customers,Orders,OrderItems
WHERE Customers.cust_id = Orders.cust_id
 AND OrderItems.order_num = Orders.order_num
 AND prod_id = 'RGAN01';

输出

+---------------+--------------------+
| cust_name     | cust_contact       |
+---------------+--------------------+
| Fun4All       | Denise L. Stephens |
| The Toy Store | Kim Howard         |
+---------------+--------------------+

此查询用来检索订购了某种产品的顾客。任何需要这个数据的人都必须理解相关表的结构,知道如何创建查询和对标的联结。

现在,假如可以把整个查询包装成一个名为ProductCustomers的虚拟表,则可以如下轻松地检索出相同的数据

SELECT cust_name, cust_contact 
FROM ProductCustomers 
WHERE prod_id = 'RGAN01'; 

这就是视图的作用。ProductCustomers是一个视图,作为一个视图,它不包含任何列和数据,包含的是一个查询(与上面用以正确连接表的相同查询)。

当然现在我们还没有创建ProductCustomers视图,是检索不出来的,所以会报如下错误:

ERROR 1146 (42S02): Table 'data.productcustomers' doesn't exist

1.1为什么使用视图呢?

下面是视图的一些常用应用

  • 重用SQL语句。
  • 简化复杂的SQL操作。在编写查询后,可以方便的重用它而不必知道其基本的查询细节。
  • 使用表的一部分而不是整个表。
  • 保护数据。可以授予用户访问表的特定部分的权限,而不是整个标的访问权限。
  • 更改 数据格式和表示。视图可以返回与底层表的表示和格式不同的数据。

创建视图后,可以用与表基本相同的方式使用它们。可以对视图执行SELECT操作,过滤和排序数据,将视图联结到其他表或者视图,甚至添加和更新数据(添加和更新数据存在某些限制。关于这个内容稍后还要做进一步的介绍)。

视图本身不包含数据,因此它们返回的数据是从其他表中检索出来的。在添加或更改这些表中的数据时,视图将返回改变过的数据。

1.2视图的规则和限制

  • 与表一样,视图必须唯一命名(不能给视图取和别的视图或者表相同的名字)。
  • 对于可创建的视图数目没有限制。
  • 为了创建视图,必须有足够的访问权限。这些限制通常由数据局管理人员授予。
  • 视图可以嵌套,即可以利用其它视图中检索数据的查询来构造一个视图。
  • ORDER BY可以用在视图中,但如果从该视图检索数据SELECT中含有ORDER BY,那么该视图中的ORDER BY 将被覆盖。
  • 视图不能索引,也不能有关联的触发器或默认值。
  • 视图可以和表一起使用。例如:编写一条联结表和视图的SELECT语句。
  • 有些DBMS要求返回所有列进行命名,如果列式计算字段,则需要使用别名。
  • 有些DBMS把视图作为只读的查询,这表示可以从视图中查询数据,但不能将数据写回底层表。
  • 有些DBMS允许创建这样的视图,它不能进行导致行不再属于视图的插入或更新。

2使用视图

视图的创建

  • 视图用CREATE VIEW语句来创建。
  • 使用SHOW CREATE VIEW viewname;来查看创建视图的语句。
  • 用DROP删除视图,其语法为DROP VIEW viewname;。
  • 更新视图时,可以先用DROP再用CREATE,也可以直接用CREATE OR REPLACE VIEW。如果要更新的视图不存在,则第2条更新语句会创建一个视图,如果要更新的视图存在,则第2条更新语句会替换原有的视图。

2.1利用视图简化复杂的联结

输入

CREATE VIEW ProductCustomers AS
SELECT cust_name, cust_contact, prod_id 
FROM Customers, Orders, OrderItems 
WHERE Customers.cust_id = Orders.cust_id 
 AND OrderItems.order_num = Orders.order_num; 

使用 show create view ProductCustomers; 查看视图

mysql> show create view ProductCustomers;
+------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+
| View             | Create View                                                                                                                                                                                                                                                                                                                                                                                          | character_set_client | collation_connection |
+------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+
| productcustomers | CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `productcustomers` AS select `customers`.`cust_name` AS `cust_name`,`customers`.`cust_contact` AS `cust_contact`,`orderitems`.`prod_id` AS `prod_id` from ((`customers` join `orders`) join `orderitems`) where ((`customers`.`cust_id` = `orders`.`cust_id`) and (`orderitems`.`order_num` = `orders`.`order_num`)) | gbk                  | gbk_chinese_ci       |
+------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+

在这里插入图片描述
分析:这条语句创建一个名为productcustomers的视图,它联结三个表,以返回已订购了任意产品的所有客户的列表。如果执行SELECT * FROM productcustomers,将列出订购了任意产品的客户

接下来检索订购了产品RGAN01的顾客,可如下进行:

SELECT cust_name, cust_contact 
FROM ProductCustomers 
WHERE prod_id = 'RGAN01';
+---------------+--------------------+
| cust_name     | cust_contact       |
+---------------+--------------------+
| Fun4All       | Denise L. Stephens |
| The Toy Store | Kim Howard         |
+---------------+--------------------+

分析:这条语句通过WHERE子句从视图中检索特定数据。当DBMS处理此查询时,它将指定的WHERE子句添加到视图查询中已有的WHERE子句中,以便正确过滤数据。

可以看出,视图极大地简化了复杂SQL语句的使用。利用视图,可一次性编写基础的SQL,然后根据需要多次使用

2.2用视图重新格式化检索出的数据

视图的另一常见用途是重新格式化检索出的数据。下面的SELECT语句(来自第10章)在单个组合计算列中返回供应商名和位置:

SELECT Concat(RTrim(vend_name), '(',RTRIM(vend_country),')')
       AS vend_title
FROM Vendors
ORDER BY vend_name;
+------------------------+
| vend_title             |
+------------------------+
| Bear Emporium(USA)     |
| Bears R Us(USA)        |
| Doll House Inc.(USA)   |
| Fun and Games(England) |
| Furball Inc.(USA)      |
| Jouets et ours(France) |
+------------------------+

把此语句转换为一个视图,如下所示

CREATE VIEW VendorLocations AS 
SELECT Concat(RTrim(vend_name), '(',RTRIM(vend_country),')')
       AS vend_title
FROM Vendors
ORDER BY vend_name;

查看视图VendorLocations

mysql> show create view VendorLocations;
+-----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+
| View            | Create View                                                                                                                                                                                                                                            | character_set_client | collation_connection |
+-----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+
| vendorlocations | CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `vendorlocations` AS select concat(rtrim(`vendors`.`vend_name`),'(',rtrim(`vendors`.`vend_country`),')') AS `vend_title` from `vendors` order by `vendors`.`vend_name` | gbk                  | gbk_chinese_ci       |
+-----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+

在这里插入图片描述
分析:这条语句使用与以前的SELECT语句相同的查询创建视图。为了检索出以创建所有邮件标签的数据,可如下进行:

SELECT * 
FROM VendorLocations; 
+------------------------+
| vend_title             |
+------------------------+
| Bear Emporium(USA)     |
| Bears R Us(USA)        |
| Doll House Inc.(USA)   |
| Fun and Games(England) |
| Furball Inc.(USA)      |
| Jouets et ours(France) |
+------------------------+

2.3用视图过滤不想要的东西

视图对于应用普通的WHERE子句也很有用。例如,可以定义customeremaillist视图,它过滤没有电子邮件地址的客户。为此目的,可使用下面的语句:

CREATE VIEW CustomerEMailList AS 
SELECT cust_id, cust_name, cust_email 
FROM Customers 
WHERE cust_email IS NOT NULL; 

分析:显然,在发送电子邮件到邮件列表时,需要排除没有电子邮件地址的用户。这里的WHERE子句过滤了cust_email列中具有NULL值的那些行,使他们不被检索出来。

SELECT * 
FROM CustomerEMailList; 
+------------+--------------+-----------------------+
| cust_id    | cust_name    | cust_email            |
+------------+--------------+-----------------------+
| 1000000001 | Village Toys | sales@villagetoys.com |
| 1000000003 | Fun4All      | jjones@fun4all.com    |
| 1000000004 | Fun4All      | dstephens@fun4all.com |
+------------+--------------+-----------------------+

2.4使用视图与计算字段

视图对于简化计算字段的使用特别有用。例如检索某个特定订单中的物品,计算每种物品的总价格:

SELECT prod_id, 
       quantity, 
       item_price, 
       quantity*item_price AS expanded_price 
FROM OrderItems 
WHERE order_num = 20008; 
+---------+----------+------------+----------------+
| prod_id | quantity | item_price | expanded_price |
+---------+----------+------------+----------------+
| RGAN01  |        5 |       4.99 |          24.95 |
| BR03    |        5 |      11.99 |          59.95 |
| BNBG01  |       10 |       3.49 |          34.90 |
| BNBG02  |       10 |       3.49 |          34.90 |
| BNBG03  |       10 |       3.49 |          34.90 |
+---------+----------+------------+----------------+

要将其转换为一个视图,可以如下进行

CREATE VIEW OrderItemsExpanded AS 
SELECT order_num, 
       prod_id, 
       quantity,
       item_price, 
       quantity*item_price AS expanded_price 
FROM OrderItems;

为检索订单20008的详细内容(上面的输出),如下进行

SELECT * 
FROM OrderItemsExpanded 
WHERE order_num = 20008;
+-----------+---------+----------+------------+----------------+
| order_num | prod_id | quantity | item_price | expanded_price |
+-----------+---------+----------+------------+----------------+
|     20008 | RGAN01  |        5 |       4.99 |          24.95 |
|     20008 | BR03    |        5 |      11.99 |          59.95 |
|     20008 | BNBG01  |       10 |       3.49 |          34.90 |
|     20008 | BNBG02  |       10 |       3.49 |          34.90 |
|     20008 | BNBG03  |       10 |       3.49 |          34.90 |
+-----------+---------+----------+------------+----------------+

这样下来我们共创建了4个视图如下:
在这里插入图片描述
可以看到视图非常容易创建,而且也很好用,它将相当于封装了一些查询语句在一个你定义的虚拟表中,将正确使用视图可以大大简化复杂数据的处理。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章