用通配符和正則表達式進行 SQL 搜索

用通配符進行過濾

LIKE 操作符

%表示任何字符出現的任意次數(0個、1個或多個字符)。


SELECT prod_id, prod_name FROM products WHERE prod_name LIKE 'jet%';

%告訴 MySQL 接受 jet 之后的任意字符,不管它有多少字符。根據 MySQL 的配置方式,搜索是可以區分大小寫的。


SELECT prod_id, prod_name FROM products WHERE prod_name LIKE '%anvil%';

通配符可以在任意位置,而且是可以多個。

%并不能匹配到 NULL

下劃線(_)通配符

下劃線與%一樣,但是下劃線只匹配單個字符而不是多個字符。


mysql> SELECT prod_id, prod_name FROM products WHERE prod_name LIKE '_ ton anvil';
+---------+-------------+
| prod_id | prod_name   |
+---------+-------------+
| ANV02   | 1 ton anvil |
| ANV03   | 2 ton anvil |
+---------+-------------+
2 rows in set (0.00 sec)

和下面的做區分:


mysql> SELECT prod_id, prod_name FROM products WHERE prod_name LIKE '% ton anvil';
+---------+--------------+
| prod_id | prod_name    |
+---------+--------------+
| ANV01   | .5 ton anvil |
| ANV02   | 1 ton anvil  |
| ANV03   | 2 ton anvil  |
+---------+--------------+
3 rows in set (0.00 sec)

** 與%能匹配0個字符不一樣,_總是匹配一個字符,不多也不少。 **

通配符使用技巧

雖然通配符很有用,但是這種功能是由代價的:通配符檢索的處理一般要比前面討論的其他搜索所花的時間更長。

  • 如果其它操作符可以達到目的,盡量不要用通配符

  • 如果確實要使用通配符,除非絕對有必要,否則不要把它們放在搜索模式的開始處,放在開始處,搜索起來是最慢的。

用正則表達式進行搜索

需要注意的是 MySQL僅支持多數正則表達式實現的一個很小的子集。

基本字符匹配

# 與文字正文1000匹配的一個正則表達式

SELECT prod_name FROM products WHERE prod_name REGEXP '1000' ORDER BY prod_name;

mysql> SELECT prod_name FROM products WHERE prod_name REGEXP '.000' ORDER BY prod_name;
+--------------+
| prod_name    |
+--------------+
| JetPack 1000 |
| JetPack 2000 |
+--------------+
2 rows in set (0.01 sec)

.表示匹配任意一個字符。

進行 OR 匹配

mysql> SELECT prod_name FROM products WHERE prod_name REGEXP '1000|2000' ORDER BY prod_name;
+--------------+
| prod_name    |
+--------------+
| JetPack 1000 |
| JetPack 2000 |
+--------------+
2 rows in set (0.01 sec)

|表示匹配其中之一。

兩個以上的 OR 條件:1000 | 2000 | 3000

匹配幾個字符之一

mysql> SELECT prod_name FROM products WHERE prod_name REGEXP '[123] Ton' ORDER BY prod_name;
+-------------+
| prod_name   |
+-------------+
| 1 ton anvil |
| 2 ton anvil |
+-------------+
2 rows in set (0.00 sec)

[123] Ton[1|2|3] Ton的縮寫,但是一定要加[]1|2|3 Ton的意思是匹配1, 2, 或3 Ton。

在集合的開始位置放一個^表示字符集合的否定,即將匹配除指定字符外的任何東西:[^123]匹配1、2、3這些字符外的任何東西。

匹配范圍

mysql> SELECT prod_name FROM products WHERE prod_name REGEXP '[1-5] Ton' ORDER BY prod_name;
+--------------+
| prod_name    |
+--------------+
| .5 ton anvil |
| 1 ton anvil  |
| 2 ton anvil  |
+--------------+

[0123456789]表示匹配數字0到9,為了簡化這種類型的集合,可用[0-9]表示。

范圍不限于完整的集合:[1-3],[6-9]。

范圍不限于數值:[a-z]匹配任意字母字符。

匹配特殊字符

要匹配特殊字符,需要用\\為前導,也就是所謂的轉義。


mysql> SELECT prod_name FROM products WHERE prod_name REGEXP '\\.' ORDER BY prod_name;
+--------------+
| prod_name    |
+--------------+
| .5 ton anvil |
+--------------+

正則表達式內具有特殊意義的所有字符都必須轉義以達到它原本意義。

\\也用來引用元字符:

元字符 說明
\f 換頁
\n 換行
\r 回車
\t 制表
\v 縱向制表

匹配反斜杠\需要使用\\\

匹配字符類

為了方便,可以使用預定義的字符集,稱為字符類(character class)

說明
[:alnum:] 任意字母和數字(同[a-zA-Z0-9])
[:alpha:] 任意字符-[a-zA-Z]
[:blank:] 空格和制表-[\t]
[:cntrl:] ASCII控制表符-ASCII0到31和127
[:digit:] 任意數字-[0-9]
[:graph:] 與[:print:]相同,但不包括空格
[:lower:] 任意小寫字母-[a-z]
[:print:] 任意可打印字符
[:space:] 包括空格在內的任意空白字符-[\f\n\r\t\v]
[:upper:] 任意大寫字母-[A-Z]
[:xdigit:] 任意十六進制數字-[a-fA-F0-9]
匹配多個實例

重復元字符:

元字符 說明
* 0或多個匹配
+ 1個或多個匹配-{1,}
? 0個或1個匹配-{0, 1}
{n} 指定數目的匹配
{n, } 不少于指定數目的匹配
{n, m} 匹配數目的范圍-m 不超過255
mysql> SELECT prod_name FROM products WHERE prod_name REGEXP '\\([0-9] sticks?\\)' ORDER BY prod_name;
+----------------+
| prod_name      |
+----------------+
| TNT (1 stick)  |
| TNT (5 sticks) |
+----------------+

mysql> SELECT prod_name FROM products WHERE prod_name REGEXP '[[:digit:]]{4}';
+--------------+
| prod_name    |
+--------------+
| JetPack 1000 |
| JetPack 2000 |
+--------------+

等價于:


SELECT prod_name FROM products WHERE prod_name REGEXP '[0-9][0-9][0-9][0-9]'
定位符

前面講的都是匹配一個串中任意位置的文本,為了匹配特定位置的文本,需要使用定位符。

元字符 說明
^ 文本的開始
$ 文本的結尾
[[:<:]] 詞的開始
[[:>:]] 詞的結尾

找出一個數(包括以小數點開始的數)開始的所有產品:

mysql> SELECT prod_name FROM products WHERE prod_name REGEXP '^[0-9\\.]' ORDER BY prod_name;
+--------------+
| prod_name    |
+--------------+
| .5 ton anvil |
| 1 ton anvil  |
| 2 ton anvil  |
+--------------+

^的雙重用途 在集合中[]用來否定該集合,否則用來指串的開始處。

使 REGEXP 起類似 LIKE 的作用

LIKE 和 REGEXP 的不同在于,LIKE 匹配整個串,而 REGEXP 匹配子串。利用定位符,通過^開始每個表達式,用$結束每個表達式,可以使 REGEXP 的作用和 LIKE 一樣。

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,572評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,071評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,409評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,569評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,360評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,895評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,979評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,123評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,643評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,559評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,742評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,250評論 5 356
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,981評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,363評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,622評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,354評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,707評論 2 370

推薦閱讀更多精彩內容