sql語法速查
簡單的select語句
使用 SELECT COLUMN 查詢單個(gè)列
在使用 SELECT 語句檢索表數(shù)據(jù)時(shí),至少需要給出兩條信息——想檢索的列名(column_name)和被檢索內(nèi)容的表名(table_name)。
SELECT `column_name`
FROM `table_name`;
當(dāng)我們想要從一個(gè)表中查詢多個(gè)列時(shí),使用的 SELECT 語句與查詢一個(gè)列時(shí)使用的語句相似,但是需要在 SELECT 關(guān)鍵字后給出多個(gè)列名,并且列名之間必須以逗號分隔。
SELECT `column_name_1`, `column_name_2` ?
FROM `table_name`;
使用 SELECT * 查詢所有列
SELECT 語句可以直接檢索表中所有信息,即檢索所有的列。
SELECT * FROM `table_name`;
使用 SELECT DISTINCT 查詢不同行
SELECT 語句會返回所有匹配的行,會遇到數(shù)據(jù)相同的情況。如果我們只想知道有哪些不同的值,即希望查詢的值都是唯一不重復(fù)的.這時(shí)候我們就需要用到 DISTINCT
關(guān)鍵字。
SELECT DISTINCT `column_name`
FROM `table_name`
使用 SELECT WHERE 對行進(jìn)行篩選過濾
SELECT WHERE
語句是篩選查詢很重要的操作,WHERE
關(guān)鍵字后面加上條件可以過濾掉我們不需要的信息,對查詢效率有著很大的提高。在使用 SELECT WHERE
語句檢索表數(shù)據(jù)時(shí),需要給出檢索的表名 (table_name)、檢索的列名 (column_name) 和操作符 (operator) 。
SELECT `column_name1`,`column_name2`…
FROM `table_name`
WHERE `column_name` operator `value`;
其中:
column_name 對應(yīng)指定列的名稱,或者是多列,用逗號(
,
)分隔開table_name 對應(yīng)查詢表的名稱
operator 為操作符,常用的有等于
=
、小于<
、大于>
、不等于<>
或!=
。
簡單的insert語句
使用 INSERT INTO 在不指定列的情況下插入數(shù)據(jù)
INSERT INTO 語句用于向表中插入新記錄,這邊介紹兩種編寫形式,第一種形式無需指定列名,第二種形式需要指定列名。
INSERT INTO `table_name`
VALUES (value1, value2, value3,...);
value1
, value2
…… 為對應(yīng)插入數(shù)據(jù)表中的值,每個(gè)值的屬性需要與對應(yīng)表中的列名屬性相匹配,而且需要把插入的信息填寫完整,否則會報(bào)錯(cuò)。
使用 INSERT INTO 在指定的列中插入數(shù)據(jù)
INSERT INTO `table_name`
(`column1`, `column2`, `column3`,...)
VALUES (value1, value2, value3,...);
其中 column1
, column2
... 為指定的列名,value1
, value2
…… 為對應(yīng)插入數(shù)據(jù)表中的值,每個(gè)值的屬性需要與對應(yīng)的列名屬性相匹配。
簡單的update語句
使用 UPDATE 更新數(shù)據(jù)
在我們平時(shí)的使用中 UPDATE
語句,也是一種較常用的 SQL 語句,它可以用來更新表中已存在的記錄。
UPDATE `table_name`
SET `column1`=value1,`column2`=value2,...
WHERE `some_column`=some_value;
注意
請注意 UPDATE 語句中的 WHERE 子句!WHERE 子句規(guī)定哪條記錄或者哪些記錄需要更新。如果您省略了 WHERE 子句,所有的記錄都將被更新!
簡單的delete語句
使用 DELETE 刪除數(shù)據(jù)
需要用到 DELETE
關(guān)鍵字對原有的數(shù)據(jù)進(jìn)行刪除
DELETE FROM `table_name`
WHERE `some_column` = `some_value`;
table_name
代表表名稱some_column
代表列名稱,如id
some_value
可以為任意值。some_column
和some_value
構(gòu)成 WHERE 子句中的搜索條件。
比較運(yùn)算符
比較運(yùn)算符
比較運(yùn)算符用于比較運(yùn)算,判斷邏輯是否成立。
A operator B
其中 operator 是比較運(yùn)算符,用于對 A
和 B
進(jìn)行比較運(yùn)算。
常用的比較運(yùn)算符有 =
(等于) 、!=
(不等于)、 <>
(不等于)、<
(小于)、<=
(小于等于)、>
(大于)、>=
(大于等于),其中 !=
和 <>
在特殊情況下用法是不同的,這里暫時(shí)不提。
比較運(yùn)算符常常與 WHERE 在一起使用。WHERE 用于邏輯判斷,WHERE 后面寫判斷的條件,滿足條件的語句會被篩選出來。
WHERE A operator B
邏輯運(yùn)算符
使用 AND 連接多條件
使用 SQL 中的邏輯運(yùn)算符 AND 可以將 WHERE 子句中兩個(gè)或兩個(gè)以上的條件結(jié)合起來,其結(jié)果是滿足 AND 連接的所有條件的數(shù)據(jù)。
SELECT `column_name`
FROM `table_name`
WHERE condition1 AND condition2;
其中:
condition
為設(shè)置的條件,最后返回的結(jié)果應(yīng)為滿足condition1
和condition2
的數(shù)據(jù)。
使用 OR 連接多個(gè)條件
使用 SQL 中的邏輯運(yùn)算符 OR 與 AND 關(guān)鍵字不同,OR 關(guān)鍵字,只要記錄滿足任意一個(gè)條件,就會被查詢出來。
語法
SELECT `column_name`
FROM `table_name`
WHERE condition1 or condition2;
其中:
condition1
和condition2
為設(shè)置的條件,最后返回的結(jié)果應(yīng)滿足condition1
或condition2
的數(shù)據(jù)。
使用 NOT 過濾不滿足條件的數(shù)據(jù)
使用 SQL 中的邏輯運(yùn)算符 NOT 可以過濾掉 WHERE 子句中不滿足條件的結(jié)果集。
SELECT `column_name`
FROM `table_name`
WHERE NOT `condition`;
其中:
condition
為設(shè)置的條件,最后返回的結(jié)果應(yīng)不滿足condition
。
特殊條件
使用 IN 查詢多條件
當(dāng)我們需要查詢單個(gè)表?xiàng)l件過多時(shí),就會用多個(gè) 'OR' 連接或者嵌套,這會比較麻煩,現(xiàn)在我們有 'IN' 能更方便的解決這一問題。
SELECT *
FROM `table_name`
WHERE `column_name` IN `value`;
使用 NOT IN 排除
前面我們已經(jīng)學(xué)習(xí)了邏輯運(yùn)算符,這里的 'IN' 也可以與邏輯運(yùn)算符 'NOT' 并用,組成 'NOT IN',表示不在集合中的所有結(jié)果。
SELECT *
FROM `table_name`
WHERE `column_name` NOT IN value;
使用 BETWEEN AND 查詢兩值間的數(shù)據(jù)范圍
BETWEEN AND 會選取介于兩個(gè)值之間的數(shù)據(jù)范圍。這些值可以是數(shù)值、文本或者日期。
請注意,在不同的數(shù)據(jù)庫中,BETWEEN 操作符會產(chǎn)生不同的結(jié)果!
在某些數(shù)據(jù)庫中,BETWEEN 選取介于兩個(gè)值之間但不包括兩個(gè)測試值的字段。
在某些數(shù)據(jù)庫中,BETWEEN 選取介于兩個(gè)值之間且包括兩個(gè)測試值的字段。
在某些數(shù)據(jù)庫中,BETWEEN 選取介于兩個(gè)值之間且包括第一個(gè)測試值但不包括最后一個(gè)測試值的字段。
因此,請檢查您的數(shù)據(jù)庫是如何處理 BETWEEN 操作符!
SELECT *
FROM `table_name`
WHERE `column_name` BETWEEN `value` AND `value`;
使用 IS NULL 查詢空數(shù)據(jù)
NULL 值代表遺漏的未知數(shù)據(jù)。默認(rèn)的,表的列可以存放 NULL 值。 如果表中的某個(gè)列是可選的,那么我們可以在不向該列添加值的情況下插入新記錄或更新已有的記錄。這意味著該字段將以 NULL 值保存。
NULL 用作未知的或不適用的值的占位符。
SELECT *
FROM `table_name`
WHERE `column_name` IS NULL;
使用 LIKE 模糊查詢
前面我們學(xué)習(xí) BETWEEN AND 和比較運(yùn)算符時(shí),和文本操作類似,比如前面課程名稱首字母的范圍,這種方案雖然可行但是不穩(wěn)定,不是直接對文本的操作。在這里我們學(xué)習(xí)使用 LIKE 更準(zhǔn)確規(guī)范得解決文本比較問題。
LIKE 比較類似我們平時(shí)用到的搜索。
SELECT *
FROM `table_name`
WHERE `column_name` LIKE ?`value`;
其中 'D%' 表示以 D 開頭的所有單詞,% 表示為通配符,可以替代 0 個(gè)或多個(gè)字符
對于SQL 中的通配符有以下類型:
通配符描述%替代 0 個(gè)或多個(gè)字符_替代一個(gè)字符[charlist]字符列中的任何單一字符或 [!charlist]不在字符列中的任何單一字符
orderby和limit
使用 ORDER BY 對數(shù)據(jù)進(jìn)行排序
1. 使用 ORDER BY 對數(shù)據(jù)進(jìn)行排序
ORDER BY 關(guān)鍵字用于對結(jié)果集按照一個(gè)列或者多個(gè)列進(jìn)行排序,其具有 ASC(升序)和 DESC(降序)兩個(gè)關(guān)鍵字,且默認(rèn)按照升序排列。
ASC :按升序排列,ORDER BY 默認(rèn)按照升序?qū)τ涗涍M(jìn)行排序,因此升序的關(guān)鍵字 ASC 可以省去不寫。
DESC:按降序排列,如果需要按照降序?qū)τ涗涍M(jìn)行排序,可以使用 DESC 關(guān)鍵字。
基本語法
SELECT `column_name`, `column_name`
FROM `table_name`
ORDER BY `column_name`, `column_name` ASC|DESC;
使用 LIMIT 限制輸出行數(shù)
LIMIT 子句用于 SELECT 中,對輸出結(jié)果集的行數(shù)進(jìn)行約束,LIMIT 接收2個(gè)參數(shù) offset 和 count,兩個(gè)參數(shù)都是整型數(shù)字,但通常只用一個(gè)。
SELECT `column_name`, `column_name`
FROM `table_name`
LIMIT `offset` , `count`;
offset :是返回集的初始標(biāo)注,起始點(diǎn)是0,不是1哦
count :制定返回的數(shù)量
算數(shù)函數(shù)
使用 AVG() 函數(shù)求數(shù)值列的平均值
平均函數(shù) AVG() 是平均數(shù) AVERAGE 的縮寫,它用于求數(shù)值列的平均值。它可以用來返回所有列的平均值,也可以用來返回特定列和行的平均值。 具體的計(jì)算過程為:其通過對表中行數(shù)計(jì)數(shù)并計(jì)算特定數(shù)值列的列值之和,求得該列的平均值。
但是當(dāng)參數(shù) column_name
列中的數(shù)據(jù)均為空時(shí),結(jié)果會返回 NULL。
SELECT AVG(`column_name`)
FROM `table_name`;
使用 MAX() 函數(shù)返回指定列中的最大值
最大值函數(shù) MAX() 用于返回指定列中的最大值。它只有一個(gè)參數(shù) column_name
,表示指定的列名。但是當(dāng)參數(shù) column_name
列中的數(shù)據(jù)均為空時(shí),結(jié)果會返回 NULL。
SELECT MAX(`column_name`)
FROM `table_name`;
使用 MIN() 函數(shù)返回指定列中的最小值
MIN() 函數(shù)的功能與 MAX() 正好相反,它用于返回指定列中的最小值。但與 MAX() 相同的是,它也只有一個(gè)參數(shù) column_name
,表示指定的列名,且當(dāng)參數(shù) column_name
列中的數(shù)據(jù)均為空時(shí),結(jié)果會返回 NULL。
SELECT MIN(`column_name`)
FROM `table_name`;
使用 SUM() 函數(shù)統(tǒng)計(jì)數(shù)值列的總數(shù)
SUM() 函數(shù)用于統(tǒng)計(jì)數(shù)值列的總數(shù)并返回其值。它只有一個(gè)參數(shù) column_name
,表示指定的列名,但是當(dāng)參數(shù) column_name
列中的數(shù)據(jù)均為空時(shí),結(jié)果會返回 NULL。
SELECT SUM(`column_name`)
FROM `table_name`;
使用 ROUND() 函數(shù)將數(shù)值四舍五入
ROUND()
函數(shù)用于把數(shù)值字段舍入為指定的小數(shù)位數(shù)。
SELECT ROUND(`column_name`, `decimals`)
FROM `table_name`;
column_name 為要舍入的字段
decimals 規(guī)定要返回的小數(shù)位數(shù)
ROUND() 函數(shù)始終返回一個(gè)值。當(dāng) decimals 為正數(shù)時(shí),column_name 四舍五入為 decimals 所指定的小數(shù)位數(shù)。當(dāng) decimals 為負(fù)數(shù)時(shí),column_name 則按 decimals 所指定的在小數(shù)點(diǎn)的左邊四舍五入。
特別的,如果 length 是負(fù)數(shù)且大于小數(shù)點(diǎn)前的數(shù)字個(gè)數(shù),ROUND() 函數(shù)將返回 0
ROUND( X ):返回參數(shù) X 四舍五入后的一個(gè)整數(shù)。
ROUND(X, D): 返回參數(shù) X 四舍五入且保留 D 位小數(shù)后的一個(gè)數(shù)字。如果 D 為 0,結(jié)果將沒有小數(shù)點(diǎn)或小數(shù)部分。
? 注意:ROUND()
返回值數(shù)據(jù)類型會被變換為一個(gè) BIGINT 。
使用 NULL() 函數(shù)判斷空值
在本小節(jié)中,我們主要介紹 SQL 中的 ISNULL()
函數(shù)和 IFNULL()
函數(shù),他們的用途都是判斷字段是否為空,但是具體的用法有些差別。
ISNULL()
函數(shù)用于判斷字段是否為 NULL,它只有一個(gè)參數(shù) column_name
為列名,根據(jù)column_name
列中的字段是否為 NULL 值返回 0 或 1。
SELECT ISNULL(`column_name`)
FROM `table_name`;
如果
column_name
列中的某個(gè)字段是 NULL 則返回 1,不是則返回 0
IFNULL()
函數(shù)也用于判斷字段是否為NULL,但是與 ISNULL()
不同的是它接收兩個(gè)參數(shù),第一個(gè)參數(shù) column_name
為列名,第二個(gè)參數(shù) value
相當(dāng)于備用值。
SELECT IFNULL(`column_name`, `value`)
FROM `table_name`;
如果
column_name
列中的某個(gè)字段是 NULL 則返回 value 值,不是則返回對應(yīng)內(nèi)容。COALESCE(column_name, value)
函數(shù)也用于判斷字段是否為NULL,其用法和IFNULL()
相同。
使用 COUNT() 函數(shù)計(jì)數(shù)
COUNT() 函數(shù)用于計(jì)數(shù),可利用其確定表中行的數(shù)目或者符合特定條件的行的數(shù)目。當(dāng)COUNT() 中的參數(shù)不同時(shí),其的用途也是有明顯的不同的,主要可分為以下三種情況:COUNT(column_name) 、COUNT( * ) 和 COUNT(DISTINCT column_name) 。
COUNT(column_name) 函數(shù)會對指定列具有的行數(shù)進(jìn)行計(jì)數(shù),但是會除去值為 NULL 的行。該函數(shù)主要用于查看各列數(shù)據(jù)的數(shù)量情況,便于統(tǒng)計(jì)數(shù)據(jù)的缺失值。
假如出現(xiàn)某一列的數(shù)據(jù)全為 NULL 值的情況, 使用COUNT( column_name ) 函數(shù)對該列進(jìn)行計(jì)數(shù),會返回 0。
SELECT COUNT(`column_name`)
FROM `table_name`;
COUNT(*) 函數(shù)會對表中行的數(shù)目進(jìn)行計(jì)數(shù),包括值為 NULL 所在行和重復(fù)項(xiàng)所在行。該函數(shù)主要用于查看表中的記錄數(shù)。
SELECT COUNT(*)
FROM `table_name`;
? 注意: COUNT(column_name) 與 COUNT(*) 的區(qū)別
COUNT(column_name) 中,如果
column_name
字段中的值為 NULL,則計(jì)數(shù)不會增加,而如果字段值為空字符串""
,則字段值會加 1COUNT() 中,除非整個(gè)記錄全為 NULL,則計(jì)數(shù)不會增加,如果存在某一個(gè)記錄不為 NULL,或者為空字符串
""
,計(jì)數(shù)值都會加 1。正常來說,表都會有主鍵,而主鍵不為空,所以 COUNT() 在有主鍵的表中等同于 COUNT(PRIMARY_KEY),即查詢有多少條記錄。
時(shí)間函數(shù)
使用 NOW() 、 CURDATE()、CURTIME() 獲取當(dāng)前時(shí)間
NOW()
可以用來返回當(dāng)前日期和時(shí)間 格式:YYYY-MM-DD hh:mm:ssCURDATE()
可以用來返回當(dāng)前日期 格式:YYYY-MM-DDCURTIME()
可以用來返回當(dāng)前時(shí)間 格式:hh:mm:ss
在使用
NOW()
和CURTIME()
時(shí),如果要精確的秒以后的時(shí)間的話,可以在()中加數(shù)字,加多少,就表示精確到秒后多少位比如
NOW(3)
就是精確到毫秒,表示為:2021-03-31 15:27:20.645
使用 DATE()、TIME() 函數(shù)提取日期和時(shí)間
SELECT DATE('2021-03-25 16:16:30') AS `date`,TIME('2021-03-25 16:16:30') ?AS `time`;
+------------+----------+
| date ? ? ? | time ? ? |
+------------+----------+
| 2021-03-25 | 16:16:30 |
+------------+----------+
1 row in set
EXTRACT() 函數(shù)提取指定的時(shí)間信息
前面我們已經(jīng)學(xué)習(xí)了 DATE 函數(shù)和 TIME 函數(shù),明白 DATE 返回日期, TIME 返回時(shí)間,如果我只想知道年份的信息或者小時(shí)的信息,那么該怎么解決呢?這時(shí),我們就可以使用 EXTRACT() 函數(shù)來解決問題。
EXTRACT() 函數(shù)用于返回日期/時(shí)間的單獨(dú)部分,如 YEAR
(年)、MONTH
(月)、DAY
(日)、HOUR
(小時(shí))、MINUTE
(分鐘)、 SECOND
(秒)。
語法
SELECT EXTRACT(unit FROM date)
FROM `table`
table 是表格名
date 參數(shù)是合法的日期表達(dá)式。
unit 參數(shù)是需要返回的時(shí)間部分,如 YEAR
、MONTH
、 DAY
、 HOUR
、MINUTE
、SECOND
等。
在一般情況下,
EXTRACT(unit FROM date)
與unit()
的結(jié)果相同。
DATE_FORMAT() 用法
我們在 SQL 中使用 DATE_FORMAT()
方法來格式化輸出 date/time。 需要注意的是 DATE_FORMAT()
函數(shù)返回的是字符串格式。
語法
SELECT DATE_FORMAT(date,format);
date
一個(gè)有效日期。
format
是 date/time 的輸出格式。
使用 DATE_ADD() 增加時(shí)間
DATE_ADD()
函數(shù)是常用的時(shí)間函數(shù)之一,用于向日期添加指定的時(shí)間間隔。
SELECT DATE_ADD(date, INTERVAL expr type)
FROM table_name
date
指代希望被操作的有效日期,為起始日期expr
是希望添加的時(shí)間間隔的數(shù)值(expr 是一個(gè)字符串,對于負(fù)值的間隔,可以以 ”-“ 開頭)type
是具體的數(shù)據(jù)類型,表示加上時(shí)間間隔的單位(可以是 MICROSECOND , SECOND , MINUTE , HOUR , DAY , WEEK , MONTH , QUARTER , YEAR 等)
使用 DATE_SUB() 減少時(shí)間
上一節(jié)了解過能夠令時(shí)間加上幾天、幾小時(shí)的函數(shù) DATE_ADD()
,對應(yīng)的,當(dāng)我們需要修改數(shù)據(jù)表中的時(shí)間,讓時(shí)間減少幾天、幾年時(shí),又該如何做呢?
我們同樣可以使用相關(guān)的時(shí)間函數(shù)對時(shí)間進(jìn)行修改。
DATE_SUB() 函數(shù)
DATE_SUB() 函數(shù)是常用的時(shí)間函數(shù)之一,用于從日期減去指定的時(shí)間間隔。它與 DATE_ADD()
函數(shù)具有相似的用法。
SELECT DATE_SUB(date, INTERVAL expr type)
FROM table_name
date
指代希望被操作的有效日期expr
是希望添加的時(shí)間間隔type
是具體的數(shù)據(jù)類型(可以是 MICROSECOND , SECOND , MINUTE , HOUR , DAY , WEEK , MONTH , QUARTER , YEAR 等)
使用時(shí)間函數(shù) DATEDIFF() 和 TIMESTAMPDIFF() 計(jì)算日期差
DATEDIFF() 常用的日期差,在 MySQL 中默認(rèn)只能計(jì)算天數(shù)差。
DATEDIFF() 用法:DATEDIFF(時(shí)間1,時(shí)間2)
SELECT DATEDIFF(時(shí)間1,時(shí)間2) AS date_diff FROM courses;
DATEDIFF() 差值計(jì)算規(guī)則:時(shí)間 1 - 時(shí)間 2
date_diff
為返回結(jié)果列名稱
約束
非空約束 NOT NULL
NOT NULL 約束強(qiáng)制列不接受 NULL 值,強(qiáng)制字段始終包含值,這意味著,如果不向字段添加值,就無法插入新紀(jì)錄或者更新記錄。
下面的 SQL 強(qiáng)制 ID
列、 LastName
列以及 FirstName
列不接受 NULL 值:
CREATE TABLE `Persons` (
? ?`ID` int NOT NULL,
? ?`LastName` varchar(255) NOT NULL,
? ?`FirstName` varchar(255) NOT NULL,
? ?`Age` int
);
在一個(gè)已創(chuàng)建的表的 Age
字段中添加 NOT NULL 約束如下所示:
ALTER TABLE `Persons`
MODIFY `Age` int NOT NULL;
在一個(gè)已創(chuàng)建的表的 Age
字段中刪除 NOT NULL 約束如下所示:
ALTER TABLE `Persons`
MODIFY `Age` int NULL;
主鍵約束 PRIMARY KEY
PRIMARY KEY 約束唯一標(biāo)識數(shù)據(jù)庫表中的每條記錄 ,簡單的說,PRIMARY KEY = UNIQUE + NOT NULL ,從技術(shù)的角度來看,PRIMARY KEY 和 UNIQUE 有很多相似之處。但還是有以下區(qū)別:
NOT NULL UNIQUE 可以將表的一列或多列定義為唯一性屬性,而 PRIMARY KEY 設(shè)為多列時(shí),僅能保證多列之和是唯一的,具體到某一列可能會重復(fù)。
PRIMARY KEY 可以與外鍵配合,從而形成主從表的關(guān)系,而 NOT NULL UNIQUE 則做不到這一點(diǎn)
如:
表一:用戶
id
(主鍵),用戶名表二: 銀行卡號
id
(主鍵),用戶id
(外鍵)則表一為主表,表二為從表。
更大的區(qū)別在邏輯設(shè)計(jì)上。 PRIMARY KEY 一般在邏輯設(shè)計(jì)中用作記錄標(biāo)識,這也是設(shè)置 PRIMARY KEY 的本來用意,而 UNIQUE 只是為了保證域/域組的唯一性。
CREATE TABLE 時(shí) 添加 PRIMARY KEY 約束
CREATE TABLE `Persons`
(
? ?`P_Id` int NOT NULL,
? ?`LastName` varchar(255) NOT NULL,
? ?`FirstName` varchar(255),
? ?`Address` varchar(255),
? ?`City` varchar(255),
? ?PRIMARY KEY (`P_Id`)
);
ALTER TABLE 時(shí)添加主鍵約束
ALTER TABLE `Persons`
ADD PRIMARY KEY (`P_Id`)
如果您使用 ALTER TABLE 語句添加主鍵,必須把主鍵列聲明為不包含 NULL 值(在表首次創(chuàng)建時(shí))。
撤銷 PRIMARY KEY
ALTER TABLE `Persons`
DROP PRIMARY KEY
外鍵約束 FOREIGN KEY
什么是外鍵
一個(gè)表中的 FOREIGN KEY 指向另一個(gè)表中的 UNIQUE KEY 。
讓我們看了例子,如果一個(gè)字段 X 在一張表(表 1 )中是關(guān)鍵字,而在另一張表(表 2 )中不是關(guān)鍵字,則稱字段 X 為表 2 的外鍵。
外鍵的作用
外鍵最根本的作用:保證數(shù)據(jù)的完整性和一致性。接下來通過一個(gè)例子來深入理解一下。
現(xiàn)在有兩張表——學(xué)生表和院系表,這里的院系就是學(xué)生表的外鍵,外鍵表是學(xué)生表,主鍵表是院系表。 假如院系表中的某個(gè)院系被刪除了,那么在學(xué)生表中要想查詢這個(gè)被刪除的院系號所對應(yīng)的院信息就會報(bào)錯(cuò),因?yàn)橐呀?jīng)不存在這個(gè)系了,所以,刪除院系表(主鍵表)時(shí)必須刪除其他與之關(guān)聯(lián)的表,這里就說明了外鍵的作用,保持?jǐn)?shù)據(jù)的一致性、完整性。 當(dāng)然反過來講,你刪除學(xué)生表中的記錄,并不影響院系表中的數(shù)據(jù),你查詢院系號也能正確查詢。 所以刪除外鍵表中的數(shù)據(jù)并不影響主鍵表。
外鍵約束
外鍵約束是指用于在兩個(gè)表之間建立關(guān)系,需要指定引用主表的哪一列。
CREATE TABLE 時(shí)的 SQL FOREIGN KEY 約束
CREATE TABLE `Orders`
(
`O_Id` int NOT NULL,
`OrderNo` int NOT NULL,
`P_Id` int,
PRIMARY KEY (O_Id),
FOREIGN KEY (P_Id) REFERENCES Persons(P_Id)
)
NOT NULL 表示該字段不為空 REFERENCES 表示 引用一個(gè)表
如需命名 FOREIGN KEY 約束,并定義多個(gè)列的 FOREIGN KEY 約束:
CREATE TABLE `Orders`
(
`O_Id` int NOT NULL,
`OrderNo` int NOT NULL,
`P_Id` int,
PRIMARY KEY (O_Id),
CONSTRAINT fk_PerOrders FOREIGN KEY (P_Id)
REFERENCES Persons(P_Id)
)
CONSTRAINT 表示約束,后面接約束名稱,常用于創(chuàng)建約束和刪除約束;
ALTER TABLE 時(shí)的 SQL FOREIGN KEY 約束
當(dāng) "Orders" 表已被創(chuàng)建時(shí),如需在 "P_Id" 列創(chuàng)建 FOREIGN KEY 約束:
ALTER TABLE `Orders`
ADD FOREIGN KEY (P_Id)
REFERENCES Persons(P_Id)
如需命名 FOREIGN KEY 約束,并定義多個(gè)列的 FOREIGN KEY 約束:
ALTER TABLE `Orders`
ADD CONSTRAINT fk_PerOrders
FOREIGN KEY (P_Id)
REFERENCES Persons(P_Id)
撤銷 FOREIGN KEY 約束
ALTER TABLE `Orders`
DROP FOREIGN KEY fk_PerOrders
檢查約束 CHECK
CHECK 約束用于限制列中的值的范圍,評估插入或修改后的值。 滿足條件的值將會插入表中,否則將放棄插入操作。 可以為同一列指定多個(gè) CHECK 約束。
CHECK
約束既可以用于某一列也可以用于某張表:
如果對單個(gè)列定義 CHECK 約束,那么該列只允許特定的值。
如果對一個(gè)表定義 CHECK 約束,那么此約束會基于行中其他列的值在特定的列中對值進(jìn)行限制。
定義 CHECK 約束條件在某種程度上類似于編寫查詢的 WHERE 子句,使用不同的比較運(yùn)算符(例如 AND、OR、BETWEEN、IN、LIKE 和 IS NULL)編寫其布爾表達(dá)式,該布爾表達(dá)式將返回 TRUE、FALSE 或 UNKNOWN 。 當(dāng)條件中存在 NULL 值時(shí),CHECK約束將返回 UNKNOWN 值。 CHECK 約束主要用于通過將插入的值限制為遵循定義的值、范圍或格式規(guī)則的值來強(qiáng)制域完整性。
CREATE DATABASE IF NOT EXISTS hardy_db default character set utf8mb4 collate utf8mb4_0900_ai_ci;
USE hardy_db;
DROP TABLE IF EXISTS lesson;
創(chuàng)建表結(jié)構(gòu)時(shí)可以使用 CHECK 約束,也可以給已創(chuàng)建的表增加 CHECK 約束。
??我們舉一個(gè)例子感受一下它的用法:
假如我們想創(chuàng)建一個(gè)簡單的課程表 ,表中每一條數(shù)據(jù)記錄著課程編號 、課程名稱 、學(xué)生總數(shù) 、創(chuàng)建課程時(shí)間 以及授課教師編號 。 其中課程編號 為主鍵。courses``id``name``student_count``created_at``teacher_id``id
根據(jù)基本常識,學(xué)生總數(shù) 一定是非負(fù)值,在這里我們設(shè)置它必須為正整數(shù),可以使用 CHECK 約束。student_count
創(chuàng)建表(CREATE TABLE)時(shí)添加 CHECK約束
在創(chuàng)建課程表 時(shí),給學(xué)生總數(shù) 字段加上一個(gè)大于 0 的約束。
CREATE TABLE `courses`
(
`id` int,
`name` varchar(255),
`student_count` int,
`created_at` date,
`teacher_id` int,
CHECK (`student_count` > 0)
)
為多個(gè)列添加 CHECK 約束
CREATE TABLE `courses`
(
`id` int,
`name` varchar(255),
`student_count` int,
`created_at` date,
`teacher_id` int,
CHECK (`student_count` > 0 AND `teacher_id` > 0)
)
如果想為一個(gè)表中多個(gè)字段添加約束,直接在 CHECK 關(guān)鍵字后的括號內(nèi)添加,兩個(gè)約束間使用 AND 關(guān)鍵字連接。
為 CHECK 約束命名
CREATE TABLE `courses`
(
`id` int,
`name` varchar(255),
`student_count` int,
`created_at` date,
`teacher_id` int,
CONSTRAINT chk_courses CHECK (`student_count` > 0) ;
)
核心部分的基本語法為:
[CONSTRAINT <constraint name>] CHECK (<condition>)
約束關(guān)鍵字 CONSTRAINT:表示其后面接的內(nèi)容為約束
constraint name:為約束名稱
關(guān)鍵字 CHECK:表示檢查約束
condition:被約束內(nèi)容
表已存在時(shí)添加 CHECK 約束
課程表 已存在的情況下為學(xué)生總數(shù) 字段添加一個(gè)大于 0 的 CHECK 約束
ALTER TABLE `courses`
ADD CHECK ( `student_count` > 0);ALTER TABLE `courses` ?
ADD CONSTRAINT chk_courses CHECK ( `student_count` > 0 AND `teacher_id` > 0);
ALTER TABLE 關(guān)鍵字:表示修改表的定義
ADD 關(guān)鍵字:表示增加
撤銷 CHECK 約束
如果想要撤銷 CHECK 約束,可以使用 DROP 關(guān)鍵字。
ALTER TABLE `courses`
DROP CHECK chk_courses
默認(rèn)約束 DEFAULT
DEFAULT 約束
默認(rèn)值(Default)”的完整稱呼是“默認(rèn)值約束(Default Constraint)”。 MySQL 默認(rèn)值約束用來指定某列的默認(rèn)值。
DEFAULT 約束用法
DEFAULT 約束用于向列中插入默認(rèn)值。
如果沒有規(guī)定其他的值,那么會將默認(rèn)值添加到所有的新記錄。
例如女同學(xué)較多,性別就可以默認(rèn)為“女”,如果插入一條新的記錄時(shí)沒有為這個(gè)字段賦值,那么系統(tǒng)會自動(dòng)為這個(gè)字段賦值為“女”。
CREATE TABLE 時(shí)的 DEFAULT 約束
使用 DEFAULT 關(guān)鍵字設(shè)置默認(rèn)值約束,具體的語法規(guī)則如下所示:
<字段名> <數(shù)據(jù)類型> DEFAULT <默認(rèn)值>
CREATE TABLE `Persons`
(
? ?`P_Id` int NOT NULL,
? ?`LastName` varchar(255) NOT NULL,
? ?`FirstName` varchar(255),
? ?`Address` varchar(255),
? ?`City` varchar(255) DEFAULT 'Sandnes'
)
通過使用類似 GETDATE() 這樣的函數(shù), DEFAULT 約束也可以用于插入系統(tǒng)值:
CREATE TABLE `Orders`
(
? ?`O_Id` int NOT NULL,
? ?`OrderNo` int NOT NULL,
? ?`P_Id` int,
? ?`OrderDate` date DEFAULT GETDATE()
)
ALTER TABLE 時(shí)的 DEFAULT 約束
如果表已被創(chuàng)建時(shí),想要在 列創(chuàng)建 DEFAULT 約束,請使用下面的 SQL:City
ALTER TABLE `Persons`
ALTER `City` SET DEFAULT 'SANDNES'
撤銷 DEFAULT 約束
ALTER TABLE `Persons`
ALTER `City` DROP DEFAULT
多表連接
聯(lián)結(jié)
我們可以舉一個(gè)生活中的例子來理解“聯(lián)結(jié)”:
在大學(xué)每一個(gè)新學(xué)期即將開始的時(shí)候,我們都會遇到一個(gè)大難題,那就是選課。
假如所有課程的信息和所有教師的信息都存放在同一張表中,我們會發(fā)現(xiàn)這顯得很繁瑣且不便于信息的更改。 因?yàn)橥粋€(gè)教師開設(shè)的不同課程對應(yīng)的教師信息都是相同的,當(dāng)教師信息改變時(shí),需要修改多條課程。
因此,為了同學(xué)們在選課時(shí)操作更便利,我們根據(jù)內(nèi)容將所有數(shù)據(jù)分解為了兩個(gè)表,即教師表和課程表。 我們可以將他們稱為關(guān)系表。 關(guān)系表就是一類數(shù)據(jù)一個(gè)表,各表通過某些關(guān)系互相關(guān)聯(lián)。
?? 那么問題就來了,數(shù)據(jù)存儲在兩個(gè)表中,如果我們想用一條 SELECT 語句同時(shí)查詢課程信息和對應(yīng)的教師信息該怎么辦呢?
答案就是——使用聯(lián)結(jié)。
簡單地說,聯(lián)結(jié)是一種機(jī)制,用于在一條 SELECT 語句中關(guān)聯(lián)多個(gè)表,返回一組輸出。
這個(gè)時(shí)候就要說一下聯(lián)結(jié)中的兩大主角——主鍵(PRIMARY KEY)*和*外鍵(FOREIGN KEY)。
以我們使用的教師表和課程表為例:
表1:courses (課程表)
列名類型注釋編號int unsigned主鍵名字瓦爾查爾課程名稱student_countint學(xué)生總數(shù)created_at日期創(chuàng)建課程時(shí)間teacher_idint講師 id
表2:teachers (教師表)
列名類型注釋編號int主鍵名字瓦爾查爾講師姓名電子郵件瓦爾查爾講師郵箱年齡int講師年齡國家瓦爾查爾講師國籍
教師表 中包含所有教師的信息,每個(gè)教師具有唯一的標(biāo)識,這個(gè)標(biāo)識被稱為主鍵(PRIMARY KEY),可以為 id 或其他唯一值。 我們這里選擇教師編號()為教師表的主鍵。teachers``id
而在課程表 中,除了教師編號 (即教師表的主鍵)外不存儲任何教師的信息。 則教師編號為課程表的外鍵(FOREIGN KEY)。courses``teacher_id
教師表的主鍵又叫作課程表的外鍵,因此這兩個(gè)表通過教師編號這一列關(guān)聯(lián)了。
?? 那我們又該如何創(chuàng)建聯(lián)結(jié)呢? 規(guī)定要聯(lián)結(jié)的所有表以及它們?nèi)绾侮P(guān)聯(lián)就可以了。
在設(shè)置關(guān)聯(lián)條件時(shí),為避免不同表被引用的列名相同,我們需要使用完全限定列名(用一個(gè)點(diǎn)分隔表名和列名),否則會返回錯(cuò)誤。
`table1`.`common_field` = `table2`.`common_field`
JOIN 連接子句
SQL JOIN 連接子句用于將數(shù)據(jù)庫中兩個(gè)或者兩個(gè)以上表中的記錄組合起來。 其類型主要分為 INNER JOIN(內(nèi)連接)、OUTER JOIN(外連接)、全連接(FULL JOIN)和交叉連接(CROSS JOIN),其中 OUTER JOIN 又可以細(xì)分為 LEFT JOIN(左連接)和 RIGHT JOIN(右連接)。
因此,我們主要使用的 JOIN 連接類型如下:
INNER JOIN:如果表中有至少一個(gè)匹配,則返回行
LEFT JOIN:即使右表中沒有匹配,也從左表返回所有的行
RIGHT JOIN:即使左表中沒有匹配,也從右表返回所有的行
FULL JOIN:只要其中一個(gè)表中存在匹配,則返回行
CROSS JOIN:又稱笛卡爾積,兩個(gè)表數(shù)據(jù)一一對應(yīng),返回結(jié)果的行數(shù)等于兩個(gè)表行數(shù)的乘積
內(nèi)連接 INNER JOIN
最常用也最重要的多表聯(lián)結(jié)類型就是 INNER JOIN(內(nèi)連接),有時(shí)候也被稱作 EQUIJOIN(等值連接)。
內(nèi)連接根據(jù)聯(lián)結(jié)條件來組合兩個(gè)表中的字段,以創(chuàng)建一個(gè)新的結(jié)果表。 假如我們想將表 1 和表 2 進(jìn)行內(nèi)連接,SQL 查詢會逐個(gè)比較表 1 和表 2 中的每一條記錄,來尋找滿足聯(lián)結(jié)條件的所有記錄對。 當(dāng)聯(lián)結(jié)條件得以滿足時(shí),所有滿足條件的記錄對的字段將會結(jié)合在一起構(gòu)成結(jié)果表。
簡單的說,內(nèi)連接就是取兩個(gè)表的交集,返回的結(jié)果就是連接的兩張表中都滿足條件的部分。

基本語法有如下兩種寫法:
SELECT `table1`.`column1`, `table2`.`column2`...
FROM `table1`
INNER JOIN `table2`
ON `table1`.`common_field` = `table2`.`common_field`;
或
SELECT `table1`.`column1`, `table2`.`column2`...
FROM `table1`
JOIN `table2`
ON `table1`.`common_field` = `table2`.`common_field`;
注:INNER JOIN 中 INNER 可以省略不寫
其中,語法的核心部分如下所示:
FROM table1
INNER JOIN table2
ON table1.common_field = table2.common_field
外連接 OUTER JOIN
在MySQL中,外連接查詢會返回所操作的表中至少一個(gè)表的所有數(shù)據(jù)記錄。 在MySQL中,數(shù)據(jù)查詢通過SQL語句 “OUTER JOIN… ON” 來實(shí)現(xiàn),外連接查詢可以分為以下三類:
左外連接
右外連接
全外連接
外連接數(shù)據(jù)查詢語法如下:
SELECT column_name 1,column_name 2 ... column_name n
? ?FROM table1
? ? ? ?LEFT | RIGHT | FULL ?(OUTER) JOIN table2
? ? ? ?ON CONDITION;
在上述語句中,參數(shù) column_name 表示所要查詢的字段名字,來源于所連接的表 table1 和 table2,關(guān)鍵字 OUTER JOIN 表示表進(jìn)行外連接,參數(shù) CONDITION 表示進(jìn)行匹配的條件。
左外連接 LEFT JOIN
外連接查詢中的左外連接就是指新關(guān)系中執(zhí)行匹配條件時(shí),以關(guān)鍵字 LEFT JOIN 左邊的表為參考表。 左外連接的結(jié)果包括 LEFT OUTER 子句中指定的左表的所有行,而不僅僅是連接列所匹配的行,這就意味著,左連接會返回左表中的所有記錄,加上右表中匹配到的記錄。 如果左表的某行在右表中沒有匹配行,那么在相關(guān)聯(lián)的結(jié)果行中,右表的所有選擇列表均為空值。
SELECT column_name 1,column_name 2 ... column_name n
? ?FROM table1
? ? ? ?LEFT JOIN table2
? ? ? ?ON CONDITION ;
右外連接 RIGHT JOIN
外連接查詢中的右外連接是指新關(guān)系中執(zhí)行匹配條件時(shí),以關(guān)鍵字 RIGHT JOIN 右邊的表為參考表,如果右表的某行在左表中沒有匹配行,左表就返回空值。
SELECT column_name 1,column_name 2 ... column_name n
? ?FROM table1
? ? ? ?RIGHT JOIN table2
? ? ? ?ON CONDITION ;
全外連接 FULL (OUTER) JOIN
FULL OUTER JOIN 關(guān)鍵字只要左表(table1)和右表(table2)其中一個(gè)表中存在匹配,則返回行。 FULL OUTER JOIN 關(guān)鍵字結(jié)合了 LEFT JOIN 和 RIGHT JOIN 的結(jié)果。
注:MySQL 數(shù)據(jù)庫不支持全連接,想要實(shí)現(xiàn)全連接可以使用 UNION ALL 來將左連接和右連接結(jié)果組合在一起實(shí)現(xiàn)全連接。
UNION :聯(lián)合的意思,即把兩次或多次查詢結(jié)果合并起來
要求:兩次查詢的列數(shù)必須一致,同時(shí),每條 SELECT 語句中的列的順序必須相同
推薦:列的類型可以不一樣,但推薦查詢的每一列,相對于的類型應(yīng)該一樣
可以來自多張表的數(shù)據(jù):多次sql語句取出的列名可以不一致,此時(shí)以第一個(gè)sql語句的列名為準(zhǔn),即UNION 結(jié)果集中的列名總是等于 UNION 中第一個(gè) SELECT 語句中的列名。 如果不同的語句中取出的行,有完全相同(這里表示的是每個(gè)列的值都相同),那么 UNION 會將相同的行合并,最終只保留一行。 也可以這樣理解,UNION 會去掉重復(fù)的行。 如果不想去掉重復(fù)的行,可以使用 UNION ALL 。 如果子句中有 order by,limit,需用括號()包起來。 推薦放到所有子句之后,即對最終合并的結(jié)果來排序或篩選。
SELECT column_name 1,column_name 2 ... column_name n
? ?FROM table1
? ? ? ?LEFT JOIN table2 ON CONDITION
UNION
SELECT column_name 1,column_name 2 ... column_name n
? ?FROM table1
? ? ? ?RIGHT JOIN table2 ON CONDITION ;
交叉連接 CROSS JOIN
什么是交叉連接
與內(nèi)連接和外連接相比,交叉連接非常簡單,因?yàn)樗淮嬖?ON 子句,那怎么理解交叉連接呢?
交叉連接:返回左表中的所有行,左表中的每一行與右表中的所有行組合。 即將兩個(gè)表的數(shù)據(jù)一一對應(yīng),其查詢結(jié)果的行數(shù)為左表中的行數(shù)乘以右表中的行數(shù)。
CROSS JOIN(交叉連接)的結(jié)果也稱作笛卡爾積,我們來簡單了解一下什么是笛卡爾積:
笛卡爾乘積是指在數(shù)學(xué)中,兩個(gè)集合 X 和 Y 的笛卡尓積(Cartesian product),又稱直積,表示為X × Y,第一個(gè)對象是 X 的成員而第二個(gè)對象是 Y 的所有可能有序?qū)Φ钠渲幸粋€(gè)成員。
交叉連接有兩種定義方式,分為隱式連接和顯式連接。 兩種定義方式的查詢結(jié)果是相同的。
隱式交叉連接:不需要使用 CROSS JOIN 關(guān)鍵字,只要在 SELECT 語句的 FROM 語句后將要進(jìn)行交叉連接的表名列出即可,這種方式基本上可以被任意數(shù)據(jù)庫系統(tǒng)支持。
SELECT `table1`.`column1`, `table2`.`column2`...
FROM `table1`,`table2`;
顯式交叉連接:與隱式交叉連接的區(qū)別就是它使用 CROSS JOIN 關(guān)鍵字,用法與 INNER JOIN 相似。
SELECT `table1`.`column1`, `table2`.`column2`...
FROM `table1`
CROSS JOIN `table2`;
分組查詢
GROUP BY 子句
GROUP BY 函數(shù)就是 SQL 中用來實(shí)現(xiàn)分組的函數(shù),其用于結(jié)合聚合函數(shù),能根據(jù)給定數(shù)據(jù)列的每個(gè)成員對查詢結(jié)果進(jìn)行分組統(tǒng)計(jì),最終得到一個(gè)分組匯總表。
SELECT `column_name`, aggregate_function(`column_name`)
FROM `table_name`
WHERE `column_name` operator value
GROUP BY `column_name`;
HAVING 子句
我們在使用 WHERE 條件子句時(shí)會發(fā)現(xiàn)其不能與聚合函數(shù)聯(lián)合使用,為解決這一點(diǎn),SQL 中提供了 HAVING 子句。 在使用時(shí), HAVING 子句經(jīng)常與 GROUP BY 聯(lián)合使用,HAVING 子句就是對分組統(tǒng)計(jì)函數(shù)進(jìn)行過濾的子句。
HAVING 子句對于 GROUP BY 子句設(shè)置條件的方式其實(shí)與 WHERE 子句與 SELECT 的方式類似,語法也相近,但 WHERE 子句搜索條件是在分組操作之前,而 HAVING 則是在之后。
SELECT ? `column_name`, aggregate_function(`column_name`)
FROM ? ? `table_name`
WHERE ? ?`column_name` operator value
GROUP BY `column_name`
HAVING ? aggregate_function(`column_name`) operator value;
子查詢
SELECT 語句中的子查詢
當(dāng)一個(gè)查詢是另一個(gè)查詢的條件時(shí),稱之為子查詢。
即在查詢語句中的 WHERE 條件子句中,又嵌套了另一個(gè)查詢語句。
因此,子查詢本質(zhì)上就是一個(gè)完整的 SELECT 語句,它可以使一個(gè) SELECT、INSERT INTO 語句、DELETE 語句或 UPDATE 語句嵌套在另一子查詢中。 子查詢的輸出可以包括一個(gè)單獨(dú)的值(單行子查詢)、幾行值(多行子查詢)、或者多列數(shù)據(jù)(多列子查詢)。
SELECT `column_name(s)`
FROM `table_name`
WHERE `column_name` OPERATOR (
? ?SELECT `column_name(s)`
? ?FROM `table_name`
);
以及,SQL語言允許多層嵌套查詢,即一個(gè)子查詢中還可以嵌套其他子查詢。
INSERT 語句中的子查詢
對于 INSERT 語句中的子查詢來說,首先是使用子查詢的 SELECT 語句找到需要插入的數(shù)據(jù),之后將返回的數(shù)據(jù)插入到另一個(gè)表中。 在子查詢中所選擇的數(shù)據(jù)可以用任何字符、日期或數(shù)字函數(shù)修改。
INSERT INTO `table_name`
SELECT `colnum_name(s)`
FROM `table_name`
[ WHERE VALUE OPERATOR ]
注意:INSERT 語句中的子查詢其實(shí)是將一個(gè)表中查詢到的數(shù)據(jù)“復(fù)制”到另一個(gè)表中,由于主鍵具有唯一性,如果需要僅在單張表中使用 INSERT 子查詢,只能在無主鍵的單張表中進(jìn)行操作,否則,需要有兩張表(如只一張表,則需新建一張表)。
UPDATE 語句中的子查詢
對于 UPDATE 語句,首先通過 SELECT 語句查詢需要更新的信息,再使用 UPDATE 語句對信息進(jìn)行更新。 當(dāng)通過 UPDATE 語句使用子查詢時(shí),能夠?qū)崿F(xiàn)表中單個(gè)列或多個(gè)列的數(shù)據(jù)更新。
UPDATE `table_name`
SET `column_name` = `new_value`
WHERE `column_name` OPERATOR
? (SELECT `column_name`
? FROM `table_name`
? [WHERE] )
注意:在 UPDATE 語句的子查詢中,子查詢 SELECT 語句所用的表和 UPDATE 語句所要更改的表不能是同一張表!
DELETE 語句中的子查詢
DELETE FROM `table_name`
WHERE `column_name` OPERATOR
? (SELECT `column_name`
? FROM `table_name` ?
? [WHERE] )
注意:在 DELETE 語句的子查詢中,子查詢 SELECT 語句所用的表和 DELETE 語句所要更改的表不能是同一張表!
內(nèi)聯(lián)視圖子查詢
內(nèi)聯(lián)視圖子查詢實(shí)際上就是將查詢的結(jié)果集作為一個(gè)查詢表,繼續(xù)進(jìn)行查詢操作。
現(xiàn)需要查詢國籍為美國(USA),且年齡最大的教師,請使用內(nèi)聯(lián)視圖子查詢實(shí)現(xiàn)。
SELECT *
FROM (
SELECT *
FROM `teachers`
WHERE `country` = 'USA'
) `T`
WHERE `age` = (
SELECT MAX(`age`)
FROM `teachers`
);
N 操作符的多行子查詢
使用 IN 操作符進(jìn)行子查詢,其實(shí)是將子查詢返回的集合和外層查詢得到的集合進(jìn)行交集運(yùn)算,這個(gè)結(jié)果可以是零個(gè)值,也可以是多個(gè)值。 由此,最后可以查詢出與列表中任意一個(gè)值匹配的行。
SELECT `column_name`
FROM `table_name`
WHERE `column_name` IN(
? ?SELECT `column_name`
? ?FROM `table_name`
? ?WHERE `column_name` = VALUE
);
ANY 操作符的多行子查詢
SELECT `column_name(s)`
FROM `table_name`
WHERE `column_name` OPERATOR
? ANY(SELECT column_name
? FROM table_name)
ALL 操作符的多行子查詢
在子查詢中使用 ALL ,表示與子查詢返回的所有值比較為真,則返回真。
SELECT `column_name(s)`
FROM `table_name`
WHERE `column_name` OPERATOR
? ALL(SELECT column_name
? FROM table_name)
多列子查詢
當(dāng)是單行多列的子查詢時(shí),主查詢語句的條件語句中引用子查詢結(jié)果時(shí)可用單行比較符號(=,>,<,>=,<=, <> 等)來進(jìn)行比較;
當(dāng)是多行多列子查詢時(shí),主查詢語句的條件語句中引用子查詢結(jié)果時(shí)必須用多行比較符號(IN,ANY,ALL 等)來進(jìn)行比較。
SELECT `name`, `age`, `country`
FROM `teachers`
WHERE (`country`, `age`) IN (
? ? ? ?SELECT `country`, MAX(`age`)
? ? ? ?FROM `teachers`
? ? ? ?GROUP BY `country`
);
HAVING 子句中的子查詢
當(dāng)子查詢出現(xiàn)在 HAVING 子句中時(shí),像 HAVING 子句中的任何表達(dá)式一樣,表示要進(jìn)行分組過濾,它被用作行組選擇的一部分,一般返回單行單列的數(shù)據(jù)。
現(xiàn)需要計(jì)算每位教師所開課程的平均學(xué)生人數(shù)與全部課程的平均學(xué)生人數(shù),比較其大小,最后返回超過全部課程平均學(xué)生人數(shù)的教師姓名,請編寫相應(yīng)的 SQL 語句實(shí)現(xiàn)。
SELECT `name`
FROM `teachers`
WHERE `id` IN (
SELECT `teacher_id`
FROM `courses`
GROUP BY `teacher_id`
HAVING AVG(`student_count`) > (
?SELECT AVG(`student_count`)
?FROM `courses`
)
);