第七章 數據過濾
7.1 組合WHERE子句
在第六章介紹的所有WHERE
子句在過濾時,使用的都是單一的條件。為了進行更強的過濾控制,MySQL允許給出多個WHERE子句,并通過AND
或OR
操作符的方式組合使用。
- 操作符(operator)
用來聯接或改變WHERE
子句中關鍵字,也成為邏輯操作符。
7.1.1 AND操作符
AND
操作符可以使用對多列的條件進行累加過濾。
- 輸入:
SELECT prod_id, prod_price, prod_name FROM products WHERE vend_id = 1003 AND prod_price <= 10;
- 輸出:略
- 分析:此語句檢索由供應商1003制造,且價格小于等于10美元的產品的編號、名稱和價格。
AND
操作符“并且”的語意。
7.1.2 OR操作符
OR操作符可以使用對多列的條件進行累加過濾。
- 輸入:
SELECT prod_id, prod_price, prod_name FROM products WHERE vend_id = 1002 OR vend_id = 1003;
- 輸出:略
- 分析:此語句檢索由供應商1002或1003制造的所有產品的編號、名稱和價格。
OR
操作符“或者”的語意。
7.1.3 計算次序
WHERE
子句可包含任意數目的AND
和OR
操作符。但是AND
的優先級比OR
高,應使用適當的圓括號分組操作符。
- 輸入:
SELECT prod_id, prod_price, prod_name FROM products WHERE (vend_id = 1002 OR vend_id = 1003) AND prod_price >= 10;
- 輸出:略
- 分析:此語句檢索由供應商為1002,或1003,價格大于等于10美元的所有產品的編號、名稱和價格。如果沒有加圓括號,則
vend_id = 1003
先和prod_price >= 10
進行AND
操作,再與vend_id = 1002
進行OR
操作,得不到想要的結果。
注意:任何時候都不應該過分依賴默認計算次序,使用圓括號可以增加可讀性,消除歧義。
7.2 IN操作符
IN
操作符用來指定條件范圍,范圍中每個條件都可以進行匹配。IN
的合法值由逗號分隔,并全部括在圓括號中。
- 輸入:
SELECT prod_id, prod_price, prod_name FROM products WHERE vend_id IN (1002,1003);
- 輸出:略
- 分析:此語句檢索由供應商1002或1003制造的所有產品的編號、名稱和價格。所完成的功能與
OR
類似。
使用IN
的優點為:
- 在使用長的合法選項清單時,IN操作符的語法更清楚更直觀。
-
IN
操作符比OR
操作符清單執行更快 -
IN
操作符最大的優點是可以包含其他SELECT
語句(將在14章說明),能夠更動態地建立WHERE
子句。
7.3 NOT操作符
WHERE子句中的NOT操作符有且只有一個功能,就是否定它之后的任何條件。
- 輸入:
SELECT prod_id, prod_price, prod_name FROM products WHERE vend_id NOT IN (1002,1003);
- 輸出:略
- 分析:此語句檢索由供應商1002或1003以外供應商提供的所有產品的編號、名稱和價格。
注意:MySQL支持使用NOT對IN、BETWEEN和EXISTS子句取反,這與其他大多數DBMS允許使用NOT對各種條件取反有很大區別。
第八章 使用通配符進行過濾
8.1 LIKE操作符
之前介紹的都是針對已知值的過濾。而對進行未知內容的匹配,可以使用通配符創建比較數據的搜索模式來完成。通配符的匹配,需要通過LIKE操作符指示MySQL完成。
通配符
用來匹配值的一部分的特殊字符。搜索模式
由字面值、通配符或兩者組合成的搜索條件。謂詞
從技術上說,LIKE
是謂詞而不是操作符,雖然結果是相同的,但是需要明白此術語。
8.1.1 百分號(%)通配符
%
表示任何字符出現任意次。例如,為了找到所有以 jet
起頭的產品,可使用以下SELECT
語句
- 輸入:
SELECT prod_id, prod_name FROM products WHERE prod_name LIKE 'jet%';
- 輸出:略
- 分析:此例子使用了搜索模式
'jet%'
,它告訴MySQL接受jet
之后任意字符,不管有多少字符。
注意:
-
%
通配符可放在搜索模式的任意位置,例如'%anvil%'
表示匹配任何位置包含anvil
的字符;'s%e'
表示以s開頭以e結尾的字符。 -
%
除了可以匹配一個或者多個字符外,還可以匹配0個字符。%代表給定位置的0、1或多個字符。 - 尾空格將影響匹配結果:
'%anvil '
將匹配不到anvil_Blank
。 -
WHERE prod_name LIKE '%'
也無法匹配NULL值作為產品名的行。
8.1.2 下劃線(_)通配符
下劃線(_
)通配符只匹配單個字符而不是多個字符。
- 輸入:
SELECT prod_id, prod_name FROM products WHERE prod_name LIKE '_ ton anvil';
- 輸出:略
- 分析:此例子使用了搜索模式
'_ ton anvil'
,它能夠匹配1 ton anvil
和2 ton anvil
,但不能匹配.5 ton anvil
,因為下劃線通配符只對應一個字,不可多也不能少 。
通配符使用技巧:
- 通配符的處理通常比值匹配花費的時間更多。不要過度使用通配符,能夠用其他操作符達到同樣目的時,應使用其他操作符。
- 除非確實有必要,否則盡量不要在模式搜索開始時使用通配符,否則速度尤其慢。
- 仔細注意通配符的位置,錯誤的位置將得不到想要的結果。
第九章 使用正則表達式進行搜索
9.1 正則表達式介紹
正則表達式是用來匹配文本的特殊串(字符集合),所有種類的程序設計語言、文本編輯器、操作系統等都支持正則表達式。
9.2 使用MySQL正則表達式
MySQL中的正則表達式僅是正則表達式的一個子集。
9.2.1 基本字符匹配
輸入:
SELECT prod_name FROM products WHERE prod_name REGEXP '1000';
輸出:略
分析:除關鍵詞字
LIKE
被REGEXP
替代外,這條語句看上去非常像LIKE
語句,但不同在于LIKE
匹配整個行,REGEXP
在列值中進行匹配,如果被匹配的值在文本中出現則匹配成功。因此,對于以上輸入,REGEXP
可以匹配到Jet 1000
,但LIKE
則匹配不到。REGEXP
可以通過定位符的使用,來匹配整個行,將在9.2.8中介紹定位符。輸入:
SELECT prod_name FROM products WHERE prod_name REGEXP '.000';
輸出:略
分析:這里使用了正則表達式
'.000'
。.
是正則表達式語言中一個特殊的字符。它表示匹配任意一個字符。因此JetPack 1000·
和JetPack 2000
都可以匹配返回。
9.2.2 進行OR匹配
為搜索兩個串之一,使用(|
)。
- 輸入:
SELECT prod_name FROM products WHERE prod_name REGEXP '1000|2000' ORDER BY prod_name ;
- 輸出:略
- 分析:這里使用了正則表達式
'1000|2000'
。|
是正則表達式語言中的OR操作符。另外,|
還支持兩個以上的條件,例如'1000|2000|3000'
。
9.2.3 匹配幾個字符之一
如果想匹配特定的單一字符,可以使用[]將一組指定的內容括起來。
- 輸入:
SELECT prod_name FROM products WHERE prod_name REGEXP '[123] ton' ORDER BY prod_name ;
*輸出:略
分析:這里使用了正則表達式'[123] ton'
。[123]
定義一組字符,意為匹配1、2或3。因此,1 ton
、2 ton
、3 ton
都能匹配。[]是另一種形式的OR語句。
注意:
- 事實上,
'[123] ton'
是'[1|2|3] ton'
的縮寫,也可以使用后者。 -
WHERE prod_name REGEXP '1|2|3 ton'
并不能得到想要的答案,因為被MySQL理解為'1'
或'2'
或‘3 ton’
。 - 字符集也可用于否定,只需要在集合開始處放置一個
^
即可。例如[^123]
可以匹配'1'
、'2'
、'3'
以外的其他字符。
9.2.4 匹配范圍
集合可用來定義要匹配一個或多個字符,此時可以使用-
來定義一個范圍,例如[0-9]
表示數字0到9,[a-z]
表示字母a到z。
- 輸入:
SELECT prod_name FROM products WHERE prod_name REGEXP '[1-5] ton' ORDER BY prod_name ;
- 輸出:略
- 分析:這里使用了正則表達式
'[1-5] ton'
。[1-5]
定義了一個范圍,表示數字1到5。
9.2.5 匹配特殊字符
正則表達式語句由具有特定含義的特殊字符構成。例如|
或-
等。如果要表示一些特殊的字母,如含.
的值,則應該使用\\\
為前導。\\\-
表示查找-
,\\\.
表示查找.
。
- 輸入:
SELECT prod_name FROM products WHERE prod_name REGEXP '\\\.' ORDER BY prod_name ;
- 輸出:略
- 分析:這里使用了正則表達式
'\\\.'
,可以順利匹配到.
。這種處理方式就是所謂的轉義,正則表達式內具有特殊意義的所有字符都需要轉義。包括. | [ ]
等,\\\\
也用來引用元字符,如下:
注意:
- 為匹配
\\
應使用\\\\\
。 - 多數正則表達式實現單個反斜桿轉義特殊字符。但MySQL要求兩個反斜桿(MySQL自己解釋一個,正則表達式解釋一個)。
9.2.6 匹配字符類
為方便常見字符集的查找,可以使用預定義的字符集。稱為字符類。如下圖所示:
9.2.7 匹配多個實例
目前為止使用的所有正則表達式都試圖匹配單詞出現。但有時需要對匹配的數目進行更強的控制,此時可以使用下列正則表達式重復元字符來完成。
輸入:
SELECT prod_name FROM products WHERE prod_name REGEXP '\\\([0-9] sticks?\\\)' ORDER BY prod_name ;
輸出:略
分析:這里使用了正則表達式'\\\([0-9] sticks?\\\)'
,?
表示,它前面的字母s出現0次或1次。輸入:
SELECT prod_name FROM products WHERE prod_name REGEXP '[[:digit:]]{4}' ORDER BY prod_name ;
輸出:略
分析:這里使用了正則表達式
'[[:digit:]]{4}'
,表示匹配連在一起的四位數字。
注意:使用正則表達式時,編寫某個特定的表達式幾乎總是有多種方法。
9.2.8 定位符
目前為止,所有例子都是匹配一個串中任意位置的文本,為了匹配特定位置的文本,需要使用定位符。
- 輸入:
SELECT prod_name FROM products WHERE prod_name REGEXP '^[0-9\\.]' ORDER BY prod_name ;
- 輸出:略
- 分析:
^
匹配串的開始,'^[0-9\\\.]'
表示匹配以數字或.
開始的串。
注意:
- ^有兩個用法,在集合中(用
[]
定義),用來表示幾何的否定,在集合外,用來表示串的起始。 -
REGEXP
用來匹配子串,LIKE用來匹配整個串,REGEXP
用^
做開頭,用$
為結束時,作用與LIKE
相同。 - 可在不使用數據庫的情況下,對正則表達式做簡單測試,
REGEXP
檢查總是返回0或1,后者表示匹配成功。例如:SELECT 'hello' FROM ‘[0-9]';
將返回0。