上個(gè)筆記主要介紹了利用SELECT語句檢索單個(gè)/多個(gè)/所有列,并利用DISTINCT關(guān)鍵字檢索具有唯一性的值、利用LIMIT/OFFSET子句限制結(jié)果;以及利用ORDER BY子句排序檢索出的數(shù)據(jù),主要有按照單個(gè)/多個(gè)列名/列位置/混合排序、用DESC關(guān)鍵字指定排序方向。
這一次我們來看一下如何使用SELECT語句的WHERE子句來指定搜索條件進(jìn)行數(shù)據(jù)過濾,包括使用=、>、<等基礎(chǔ)操作符的基礎(chǔ)數(shù)據(jù)過濾;使用AND、OR、IN、NOT操作符的高級(jí)數(shù)據(jù)過濾;以及使用%、_、[]通配符的數(shù)據(jù)過濾操作,以及實(shí)際使用中的一些細(xì)節(jié)。
1.過濾數(shù)據(jù)(WHERE子句)
數(shù)據(jù)庫(kù)表一般包含大量的數(shù)據(jù),很少需要檢索表中的所有行。通常只會(huì)根據(jù)特定操作或報(bào)告的需要 提取表數(shù)據(jù)的子集 。
只檢索所需數(shù)據(jù)需要指定搜索條件 (search criteria),或稱為過濾條件 (filter condition)。
在SELECT語句中,數(shù)據(jù)根據(jù)WHERE子句 中指定的過濾條件 進(jìn)行過濾 。
WHERE子句位置 :在表名(FROM子句)之后給出。
通過非選擇列 進(jìn)行過濾。用非檢索的列 過濾數(shù)據(jù)也是是完全合法的。
1.1 WHERE子句操作符
注意:操作符兼容 。表中所列出的操作符是冗余的,有功能相同的操作符。具體DBMS 支持的操作符不一樣。
經(jīng)過嘗試,MySQL 中除不支持!<、!>這兩個(gè)操作符外,其他都支持。
SQL過濾 or 在應(yīng)用層過濾?通常最好 選擇SQL過濾。
1.2 過濾操作
1.2.1 檢查單個(gè) 值
SELECT 列名1,列名2
FROM 表
WHERE 列名1 < 10;
1.2.2 不匹配 檢查(!=、<>操作符)
SELECT 列名1,列名2
FROM 表
WHERE 列名1 <> 'DLL01';
提示:
單引號(hào)用來限定字符串 。若將值 與字符串類型的列 進(jìn)行比較,就需要限定引號(hào);若將值與數(shù)值列 進(jìn)行比較,則不用引號(hào)。
1.2.3 范圍值 檢查(BETWEEN操作符)
SELECT 列名1,列名2
FROM 表
WHERE 列名1 BETWEEN 5 AND 10;
提示:
在使用BETWEEN操作符時(shí),必須指定 兩個(gè)值:所需范圍的低端值和高端值。(閉區(qū)間 )
并且這兩個(gè)值必須 用AND關(guān)鍵字 分隔。
1.2.4 空值 檢查(IS NULL操作符)
SELECT 列名1,列名2
FROM 表
WHERE 列名1 IS NULL;
分析:
在創(chuàng)建表時(shí),表設(shè)計(jì)人員可以指定其中的列能否不包含值 。在一個(gè)列不包含值 時(shí),稱其包含空值NULL 。
NULL:無值(no value),它與字段包含0 、空字符串 或僅僅包含空格 不同。
提示:各DBMS 特有 的操作符。
許多DBMS 擴(kuò)展 了標(biāo)準(zhǔn)操作符集 ,提供了更高級(jí)的過濾選擇,想了解可以參閱相應(yīng)DBMS文檔 。
注意:NULL和非匹配。
在進(jìn)行匹配 過濾或非匹配 過濾時(shí),不會(huì)返回含NULL值 的行。
因此過濾數(shù)據(jù)時(shí),一定要驗(yàn)證被過濾列中含NULL值 的行確實(shí)出現(xiàn)在返回的數(shù)據(jù)中。
2.高級(jí)數(shù)據(jù)過濾(組合WHERE子句)
在上一小節(jié)中,所有的WHERE子句在過濾數(shù)據(jù)時(shí)使用的都是單一 的條件。為了進(jìn)行更強(qiáng) 的過濾控制,SQL允許給出多個(gè)WHERE子句 。這些句子有兩種 使用方式:以AND子句 或OR子句 的方式使用。
操作符(operator):用來聯(lián)結(jié)或改變 WHERE子句中的//子句//的關(guān)鍵字 ,也稱為邏輯操作符(logical operator)。
下面我們就來分別介紹一下AND、OR、IN、NOT四種 操作符。
2.1 AND操作符
要通過不止一個(gè)列 進(jìn)行過濾,可以使用AND操作符 給WHERE子句附加條件 。
SELECT 列名1,列名2,列名3
FROM 表
WHERE 列名1 = 值1 AND 列名2 <= 值2;
分析:
AND:用在WHERE子句 中的關(guān)鍵字,用來表示//檢索(v)//滿足所有給定條件 的行。
這個(gè)例子中只有兩個(gè)過濾條件??梢栽黾?strong>多個(gè)過濾條件,每個(gè)條件間 都要使用AND 關(guān)鍵字。
注意:
例子中省略了ORDER BY子句。因此不同情況下做出來的輸出,順序 可能不同??梢栽赪HERE子句之后加上一個(gè)ORDER BY子句 。
2.2 OR操作符
SELECT 列名1,列名2,列名3
FROM 表
WHERE 列名1 = 值1 OR 列名2 = 值2;
分析:
OR:用在WHERE子句中的關(guān)鍵字,用來表示//檢索(v)//滿足任一給定條件 的行。(可以看出,OR的功能與AND正好相反 。)
提示:
許多DBMS在OR WHERE子句的第一個(gè)條件 得到滿足時(shí),不管 第二個(gè)條件是否滿足,相應(yīng)的行都將被檢索出來。
2.3 求值順序(AND與OR結(jié)合時(shí))
WHERE子句可以包含任意數(shù)目 的AND和OR操作符。允許兩者結(jié)合 進(jìn)行復(fù)雜、高級(jí)的過濾。
提示:在結(jié)合 AND和OR時(shí),要注意求值的順序(優(yōu)先級(jí) ):
SQL(像多數(shù)語言 一樣)在處理OR操作符前,優(yōu)先處理AND操作符。
優(yōu)先級(jí) :圓括號(hào) > AND > OR。在三者中圓括號(hào)的優(yōu)先級(jí)最高。
任何時(shí)候 使用具有AND和OR操作符 的WHERE子句,都應(yīng)該使用圓括號(hào) 明確地分組操作符。
2.4 IN操作符
SELECT 列名1,列名2,列名3
FROM 表
WHERE 列名1 IN (值1,值2)
ORDER BY 列名2;
分析:
IN后跟一組由逗號(hào) 分隔,括在圓括號(hào) (必須)中的合法值 。
IN操作符用來指定條件范圍 ,范圍中的//每個(gè)條件 都可以進(jìn)行匹配。功能與OR相當(dāng) ,下面看一個(gè)實(shí)例:
語句1:
SELECT prod_name,prod_price
FROM Products
WHERE vend_id IN ('DLL01','BRS01')
ORDER BY prod_name;
語句2:
SELECT prod_name,prod_price
FROM Products
WHERE vend_id ='DLL01' OR vend_id = 'BRS01'
ORDER BY prod_name;
語句1與語句2輸出完全一樣。
注意:使用OR時(shí),即使檢索同一個(gè)列的不同值,也不可以直接:vend_id ='DLL01' OR 'BRS01'
那么,既然IN與OR功能相當(dāng),我們?yōu)槭裁催€要使用IN操作符呢?IN操作符的優(yōu)點(diǎn)如下:
語法 更清楚、直觀;
在與其他AND和OR操作符組合使用IN時(shí),求值順序 更容易管理;
IN操作符一般比一組OR操作符執(zhí)行得更快 。
最大優(yōu)點(diǎn):IN操作符可以包含其他SELECT語句 ,能夠更動(dòng)態(tài) 地建立WHERE子句。(后續(xù)的筆記中,還會(huì)對(duì)此做詳細(xì)介紹。)
2.5 NOT操作符
SELECT 列名1
FROM 表
WHERE NOT 列名1 = 值1
ORDER BY 列名1;
上面這個(gè)例子也可以使用<>或!=操作符來完成。
分析:
NOT操作符:有且只有 一個(gè)功能,即否定 其后所跟的任何條件 。
NOT 從不 單獨(dú)使用,所以它的語法與其他操作符有所不同??梢杂迷谝^濾的列前 ,也可以用在要過濾的列后 。
說明:
大多數(shù)DBMS:允許使用NOT否定任何條件 。
MariaDB:支持使用NOT否定IN、BETWEEN和EXISTS子句。
NOT的優(yōu)點(diǎn):
對(duì)于上面例子中簡(jiǎn)單 的WHERE子句,使用NOT確實(shí)沒有什么優(yōu)勢(shì)。
但是在更復(fù)雜 的子句中,NOT是非常有用的。比如,在與IN操作符 聯(lián)合使用時(shí),NOT可以非常簡(jiǎn)單地找出與條件列表 不匹配的行。
3.用通配符進(jìn)行過濾(LIKE + 通配符)
前面所介紹的所有操作符 都是針對(duì)已知(完整)值 進(jìn)行過濾的。但是這種過濾方法并不是任何時(shí)候都好用。有些時(shí)候需要利用通配符,來創(chuàng)建(v)//用于比較(v)特定數(shù)據(jù) 的//搜索模式。
通配符(wildcard):用來匹配值的一部分 的特殊字符。
搜索模式(search pattern):由字面值(已知值)、通配符或兩者組合構(gòu)成的搜索條件 。
通配符本身實(shí)際上是SQL的WHERE子句 中有特殊含義 的字符 ,SQL支持幾種通配符。
LIKE操作符:
為在搜索句子中使用通配符,必須 使用LIKE操作符。
LIKE指示DBMS,后跟的搜索模式 利用通配符匹配 ,而不是簡(jiǎn)單的相等匹配進(jìn)行比較。
注意:
通配符搜索,只能用于文本 字段(字符串 ),非文本 數(shù)據(jù)類型字段不能使用通配符搜索。
謂詞(predicate)(選看):
操作符何時(shí)不是操作符?答案是,它作為謂詞 時(shí)。
從技術(shù) 上說,LIKE是謂詞 而不是操作符。雖然最終的結(jié)果是相同的 ,但應(yīng)對(duì)此術(shù)語有所了解,以免在SQL文獻(xiàn)或手冊(cè)中遇到此術(shù)語時(shí)不知所云。
3.1 百分號(hào)(%)通配符
語句:
SELECT 列名1,列名2,列名3
FROM 表
WHERE 列名1 LIKE 'Fish%';
分析:
%是最常用 的通配符。
在搜索串中,%表示任何字符 (除NULL)出現(xiàn)任意次數(shù) (包括0次)。
通配符(不止是%)可以在搜索模式 中的任意位置 使用,并且可以使用多個(gè) 通配符。
說明:
Access通配符。如果使用的是Microsoft Access,需要使用*而不是%。
區(qū)分大小寫 。根據(jù)DBMS 的不同及其配置 ,搜索可以是區(qū)分大小寫的。
注意:
注意字符串后面所跟的空格 ,包括Access在內(nèi)的許多DBMS都用空格來填補(bǔ)字段的內(nèi)容。(經(jīng)過測(cè)試,默認(rèn)設(shè)置的MySQL中沒有填補(bǔ)空格的機(jī)制。)
例如,如果某列有50個(gè)字符,而存儲(chǔ)的文本為Fish bean bag toy(17個(gè)字符),則為填滿該列需要在文本后附加33個(gè)空格。
這樣做一般對(duì)數(shù)據(jù)及其使用沒有影響,但是可能對(duì)某些SQL語句有負(fù)面影響。
例如,子句WHERE prod_name LIKE 'F%y'只匹配以F開頭,以y結(jié)尾的prod_name。如果值后面跟空格,則不是以y結(jié)尾,那么最終檢索結(jié)果就不是我們預(yù)想的。
- 解決辦法:簡(jiǎn)單的,給搜索模式再增加一個(gè)%,即'F%y%';
更好的解決辦法,用函數(shù)去掉空格(后面詳細(xì)介紹)
注意NULL。通配符%無法匹配NULL。
3.2 下劃線(_)通配符
SELECT 列名1,列名2
FROM 表
WHERE 列名1 LIKE '__ inch teddy bear';
分析:
-總是剛好 匹配一個(gè) 字符,不能多也不能少。
%可以匹配0個(gè)、1個(gè)、多個(gè)字符。
說明:
DB2不支持通配符_
Access通配符。如果使用的是Microsoft Access,需要使用?而不是_。
3.3 方括號(hào)([])通配符(MySQL不支持)
SELECT 列名1
FROM 表
WHERE 列名1 LIKE '[JM]%'
ORDER BY 列名1;
分析:
[]通配符用來指定一個(gè)字符集 ,它必須(也只能)匹配指定位置 (通配符的位置)的一個(gè) 字符。
此通配符可以用前綴字符(脫字號(hào)^)來否定 。也可以使用NOT操作符 得到類似的結(jié)果
,^的唯一優(yōu)點(diǎn) 是在使用多個(gè)WHERE子句時(shí)可以簡(jiǎn)化語法 。
說明:
并不總是支持集合。與前面描述的通配符不一樣,并不是 所有DBMS都支持用來創(chuàng)建集合的[]。只有Access和SQL Server支持集合。(經(jīng)過測(cè)試,MySQL 確實(shí)不支持 這個(gè)操作。)
Access中需要用!而不是^來否定一個(gè)集合。即,用[!JM],而不是[ ^JM]。
3.4 使用通配符的技巧
正如本節(jié)我們介紹,SQL的通配符很擁有。但是這種功能是有代價(jià)的,即通配符搜索 一般比前面討論的其他搜索 要耗費(fèi)更長(zhǎng) 的處理時(shí)間。
使用通配符的技巧 :
不要過度使用通配符。其他操作符能達(dá)到相同的目的,盡量使用其他操作符 。
確實(shí)需要使用通配符時(shí),盡量不要 把它們放在搜索模式 的開始處 。
仔細(xì)注意通配符的位置 。如果放錯(cuò)地方,可能不會(huì)返回我們想要的數(shù)據(jù)。
總之,通配符是一種極其重要和有用 的搜索工具 ,以后我們經(jīng)常會(huì)用到它。
參考資料:
1.《SQL必知必會(huì)》Ben Forta。