在數據庫中如何使用視圖

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個視圖如下:
在這裏插入圖片描述
可以看到視圖非常容易創建,而且也很好用,它將相當於封裝了一些查詢語句在一個你定義的虛擬表中,將正確使用視圖可以大大簡化複雜數據的處理。

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