1. 程式人生 > 資料庫 >mysql檢視之建立檢視(CREATE VIEW)和使用限制例項詳解

mysql檢視之建立檢視(CREATE VIEW)和使用限制例項詳解

本文例項講述了mysql檢視之建立檢視(CREATE VIEW)和使用限制。分享給大家供大家參考,具體如下:

mysql5.x 版本之後支援資料庫檢視,在mysql中,檢視的幾乎特徵符合SQL:2003標準。 mysql以兩種方式處理對檢視的查詢:

  • 第一種方式,MySQL會根據檢視定義語句建立一個臨時表,並在此臨時表上執行傳入查詢。
  • 第二種方式,MySQL將傳入查詢與查詢定義為一個查詢並執行組合查詢。

mysql支援版本系統的檢視,當每次檢視被更改或替換時,檢視的副本將在駐留在特定資料庫資料夾的arc(archive)資料夾中備份。備份檔案的名稱為view_name.frm-00001。如果再次更改檢視,mysql將建立一個名為view_name.frm-00002的新備份檔案。mysql允許基於其他檢視建立檢視,就是在檢視定義的select語句中,可以引用另一個檢視。

好啦,多的咱就不贅述了,接下來咱們嘗試使用CREATE VIEW語句建立檢視,先來看下語法結構:

CREATE 
  [ALGORITHM = {MERGE | TEMPTABLE | UNDEFINED}]
VIEW [database_name].[view_name] 
AS
[SELECT statement]

然後我們來詳細看下上面的sql中的各種詞是什麼意思。首先,第一個中括號裡代表的就是建立檢視是的演算法屬性,它允許我們控制mysql在建立檢視時使用的機制,並且mysql提供了三種演算法:MERGE,TEMPTABLE和UNDEFINED。我們來分別看下:

  • 使用MERGE演算法,mysql首先將輸入查詢與定義檢視的select語句組合成單個查詢。 然後mysql執行組合查詢返回結果集。 如果select語句包含集合函式(如min,max,sum,count,avg等)或distinct,group by,havaing,limit,union,union all,子查詢,則不允許使用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表來建立一個表示每個訂單的總銷售額的檢視:

CREATE VIEW SalePerOrder AS
  SELECT 
    orderNumber,SUM(quantityOrdered * priceEach) total
  FROM
    orderDetails
  GROUP by orderNumber
  ORDER BY total DESC;

我們如果使用SHOW TABLES命令來檢視示例資料庫(yiibaidb)中的所有表,還會看到SalesPerOrder檢視也顯示在表的列表中:

mysql> SHOW TABLES;
+--------------------+
| Tables_in_yiibaidb |
+--------------------+
| article_tags    |
| contacts      |
| customers     |
| departments    |
| employees     |
| offices      |
| offices_bk     |
| offices_usa    |
| orderdetails    |
| orders       |
| payments      |
| productlines    |
| products      |
| saleperorder    |
+--------------------+
14 rows in set

這是因為檢視和表共享相同的名稱空間。要知道哪個物件是檢視或表,就得使用SHOW FULL TABLES命令,如下所示:

mysql> SHOW FULL TABLES;
+--------------------+------------+
| Tables_in_yiibaidb | Table_type |
+--------------------+------------+
| article_tags    | BASE TABLE |
| contacts      | BASE TABLE |
| customers     | BASE TABLE |
| departments    | BASE TABLE |
| employees     | BASE TABLE |
| offices      | BASE TABLE |
| offices_bk     | BASE TABLE |
| offices_usa    | BASE TABLE |
| orderdetails    | BASE TABLE |
| orders       | BASE TABLE |
| payments      | BASE TABLE |
| productlines    | BASE TABLE |
| products      | BASE TABLE |
| saleperorder    | VIEW    |
+--------------------+------------+
14 rows in set

結果集中的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 |
|-- 此處省略了many many資料-- |
|    10116 | 1627.56 |
|    10158 | 1491.38 |
|    10144 | 1128.20 |
|    10408 | 615.45  |
+-------------+----------+
327 rows in set

我們再來基於另一個檢視建立一個檢視,比如,根據SalesPerOrder檢視建立名為大銷售訂單(BigSalesOrder)的檢視,以顯示總計大於60,000的每個銷售訂單,如下所示:

CREATE VIEW BigSalesOrder AS
  SELECT 
    orderNumber,ROUND(total,2) as total
  FROM
    saleperorder
  WHERE
    total > 60000;

現在,我們可以從BigSalesOrder檢視查詢資料,如下所示:

SELECT 
  orderNumber,total
FROM
  BigSalesOrder;

執行上面查詢語句,得到以下結果:

+-------------+----------+
| orderNumber | total  |
+-------------+----------+
|    10165 | 67392.85 |
|    10287 | 61402.00 |
|    10310 | 61234.67 |
+-------------+----------+
3 rows in set

完事我們再來嘗試使用inner join建立包含客戶編號和客戶支付的總金額的檢視,如下所示:

CREATE VIEW customerOrders AS
  SELECT 
    c.customerNumber,p.amount
  FROM
    customers c
      INNER JOIN
    payments p ON p.customerNumber = c.customerNumber
  GROUP BY c.customerNumber
  ORDER BY p.amount DESC;

我們使用下面的sql來查詢customerOrders檢視中的資料:

+----------------+-----------+
| customerNumber | amount  |
+----------------+-----------+
|      124 | 101244.59 |
|      321 | 85559.12 |
|      239 | 80375.24 |
| **** 此處省略了many many資料 ***|
|      219 | 3452.75  |
|      216 | 3101.4  |
|      161 | 2434.25  |
|      172 | 1960.8  |
+----------------+-----------+
98 rows in set

再來嘗試使用子查詢建立包含價格高於所有產品的平均價格的產品的檢視,如下所示:

CREATE VIEW aboveAvgProducts AS
  SELECT 
    productCode,productName,buyPrice
  FROM
    products
  WHERE
    buyPrice > 
 (SELECT 
        AVG(buyPrice)
      FROM
        products)
  ORDER BY buyPrice DESC;

我們來查詢aboveAvgProducts檢視的資料:

SELECT 
  *
FROM
  aboveAvgProducts;

執行上面查詢語句,得到以下結果:

+-------------+-----------------------------------------+----------+
| productCode | productName               | buyPrice |
+-------------+-----------------------------------------+----------+
| S10_4962  | 1962 LanciaA Delta 16V         | 103.42  |
| S18_2238  | 1998 Chrysler Plymouth Prowler     | 101.51  |
| S10_1949  | 1952 Alpine Renault 1300        | 98.58  |
|************* 此處省略了many many資料 *********************************|
| S18_3320  | 1917 Maxwell Touring Car        | 57.54  |
| S24_4258  | 1936 Chrysler Airflow          | 57.46  |
| S18_3233  | 1985 Toyota Supra            | 57.01  |
| S18_2870  | 1999 Indy 500 Monte Carlo SS      | 56.76  |
| S32_4485  | 1974 Ducati 350 Mk3 Desmo        | 56.13  |
| S12_4473  | 1957 Chevy Pickup            | 55.7   |
| S700_3167  | F/A 18 Hornet 1/72           | 54.4   |
+-------------+-----------------------------------------+----------+
54 rows in set

好啦,到這裡了,檢視的建立和使用已經介紹的差不多了。但是,檢視就沒有什麼使用的限制麼?答案當然是有的,我們來分別看下。

首先,我們不能在檢視上建立索引,再來就是當使用合併演算法的檢視查詢資料時,mysql會使用底層表的索引,還有就是對於使用誘惑演算法的檢視,當我們針對檢視查詢資料時,不會使用索引。

還有就是要注意在mysql5.7.7之前版本,是不能在SELECT語句的FROM子句中使用子查詢來定義檢視的。

再來就是如果刪除或重新命名檢視所基於的表,則mysql不會發出任何錯誤。但是,mysql會使檢視無效,我們可以使用CHECK TABLE語句來檢查檢視是否有效。

一個簡單的檢視可以更新表中資料,但是基於具有連線,子查詢等的複雜select語句建立的檢視無法更新。

mysql不像Oracle、PostgreSQL等其他資料庫系統那樣支援物理檢視,mysql是不支援物理檢視的。

好啦,關於檢視本次就記錄到這裡了。

更多關於MySQL相關內容感興趣的讀者可檢視本站專題:《MySQL查詢技巧大全》、《MySQL事務操作技巧彙總》、《MySQL儲存過程技巧大全》、《MySQL資料庫鎖相關技巧彙總》及《MySQL常用函式大彙總》

希望本文所述對大家MySQL資料庫計有所幫助。