參考資料:
《SQL基礎(chǔ)教程》

視圖
視圖和表
從SQL的角度來看,視圖就是一張表,兩者的區(qū)別在于是否保存了實(shí)際的數(shù)據(jù)。
- 創(chuàng)建表時(shí),會(huì)通過
INSERT語句將數(shù)據(jù)保存到數(shù)據(jù)庫中,而數(shù)據(jù)庫中的數(shù)據(jù)實(shí)際上會(huì)保存到計(jì)算機(jī)的存儲(chǔ)設(shè)備。 - 使用視圖時(shí),并不會(huì)將數(shù)據(jù)保存到任何地方,實(shí)際上視圖保存的是
SELECT語句。從視圖讀取數(shù)據(jù)時(shí),視圖會(huì)在內(nèi)部執(zhí)行該SELECT語句并創(chuàng)建出一張臨時(shí)表。

總結(jié)成一句話:表中存儲(chǔ)的是實(shí)際數(shù)據(jù),視圖本質(zhì)上就是SELECT語句。
視圖的優(yōu)點(diǎn)
- 視圖無需保存數(shù)據(jù),節(jié)省存儲(chǔ)設(shè)備容量;
- 可以將頻繁使用的
SELECT語句保存成視圖,就不用每次都重新書寫了。
創(chuàng)建和使用視圖
創(chuàng)建視圖的CREATE VIEW語句
CREATE VIEW 視圖名稱 (<視圖列名1>, <視圖列名2>, ...)
AS
<SELECT語句>
注意:SELECT語句中列的排列順序和視圖中列的排列順序相同,SELECT語句中的第1列就是視圖中的第1列,以此類推。視圖的列名在視圖名稱之后的列表中定義。
創(chuàng)建ProductSum視圖
CREATE VIEW ProductSum (product_type, cnt_product)
AS
SELECT product_type, COUNT(*)
FROM Product
GROUP BY product_type;

使用視圖
SELECT
product_type,
cnt_product
FROM ProductSum;

執(zhí)行結(jié)果:

在FROM子句中使用視圖查詢的兩個(gè)步驟
- 創(chuàng)建視圖:執(zhí)行定義視圖的
SELECT語句; - 使用視圖:根據(jù)得到的結(jié)果,再執(zhí)行在
FROM子句中使用視圖的SELECT語句。
當(dāng)然,我們還可以以視圖為基礎(chǔ)再創(chuàng)建視圖,因此,使用視圖的查詢通常需要執(zhí)行2條以上的SELECT語句。但是,多重視圖會(huì)降低SQL的性能,因此希望大家使用單一視圖。
視圖的限制
定義視圖時(shí)不能使用ORDER BY子句
為什么不能使用ORDER BY子句?
因?yàn)橐晥D和表一樣,數(shù)據(jù)行都是沒有順序的。
對(duì)視圖進(jìn)行更新
在SELECT語句中,視圖可以和表一樣使用,那么,更新語句(INSERT、DELETE、UPDATE)呢?
標(biāo)準(zhǔn)SQL中規(guī)定:如果定義視圖的SELECT語句能夠滿足某些條件,那么這個(gè)視圖就可以被更新。
幾個(gè)具有代表性的條件:
-
SELECT子句中未使用DISTINCT -
FROM子句中只有一張表 - 未使用
GROUP BY子句 - 未使用
HAVING子句
刪除視圖
刪除視圖的DROP VIEW語句
DROP VIEW 視圖名稱
刪除視圖ProductSum
DROP VIEW ProductSum;
子查詢
子查詢和視圖
子查詢就是一次性的視圖(SELECT語句),子查詢?cè)?code>SELECT語句執(zhí)行完畢之后就會(huì)消失。
子查詢
-- 和上面使用ProductSum視圖實(shí)現(xiàn)相同功能的子查詢語句
SELECT
product_type,
cnt_product
FROM (
SELECT
product_type,
COUNT(*) AS cnt_product
FROM Product
GROUP BY product_type
) AS ProductSum;

執(zhí)行結(jié)果:

子查詢SELECT語句的執(zhí)行順序

由內(nèi)到外:
- 首先執(zhí)行
FROM子句中的SELECT語句; - 根據(jù)1的結(jié)果執(zhí)行外層的
SELECT語句。
注意:子查詢的層數(shù)原則上沒有限制,可以無限嵌套下去,但是,隨著層數(shù)增加,SQL語句會(huì)變得越來越難讀懂,性能也會(huì)越來越差。因此,盡量避免使用多層嵌套的子查詢。
子查詢的名稱
原則上子查詢必須設(shè)定名稱,設(shè)定名稱是需要使用AS關(guān)鍵字,有時(shí)也可以省略。
標(biāo)量子查詢
標(biāo)量子查詢就是返回單一值的子查詢,必須而且只能返回表中某一行的某一列的值。
在WHERE子句中使用標(biāo)量子查詢
如何查詢出銷售單價(jià)高于平均銷售單價(jià)的商品?
我們可能會(huì)想到以下錯(cuò)誤的SQL語句:
-- 在WHERE子句中不能使用聚合函數(shù)
SELECT
product_id,
product_name,
sale_price
FROM Product
WHERE sale_price > AVG(sale_price);
雖然這樣的SELECT語句看上去能夠滿足我們的要求,但是由于在WHERE子句中不能使用聚合函數(shù),因此這樣的SELECT語句是錯(cuò)誤的。
這時(shí),標(biāo)量子查詢就可以發(fā)揮它的功效了。
計(jì)算平均銷售單價(jià)的標(biāo)量子查詢
SELECT AVG(sale_price)
FROM Product;
執(zhí)行結(jié)果:

選出銷售單價(jià)高于平均單價(jià)的商品
SELECT
product_id,
product_name,
sale_price
FROM Product
WHERE sale_price > (SELECT AVG(sale_price)
FROM Product);

執(zhí)行結(jié)果:

標(biāo)量子查詢的書寫位置
通常任何可以使用單一值的位置都可以使用標(biāo)量子查詢,也就是說,能夠使用常數(shù)或者列名的地方,無論是SELECT子句、GROUP BY子句、HAVING子句,還是ORDER BY子句,都可以使用。
注意:如果子查詢返回了多行結(jié)果,那么它就不再是標(biāo)量子查詢,而僅僅只是一個(gè)普通的子查詢,因此不能被用在需要單一輸入值的地方。
關(guān)聯(lián)子查詢
通過關(guān)聯(lián)子查詢按照商品種類對(duì)平均銷售單價(jià)進(jìn)行比較
SELECT
product_id,
product_name,
sale_price
FROM Product AS P1
WHERE sale_price > (SELECT AVG(sale_price)
FROM Product AS P2
WHERE P1.product_type = P2.product_type);

執(zhí)行結(jié)果:

這里起關(guān)鍵作用的就是在子查詢中添加WHERE子句的條件,該條件的意思就是,在同一商品種類中對(duì)各商品的銷售單價(jià)和平均單價(jià)進(jìn)行比較。
我的博客即將同步至騰訊云+社區(qū),邀請(qǐng)大家一同入駐:
https://cloud.tencent.com/developer/support-plan?invite_code=1979ipzwsgq9u