MySQL也有正規表達式,可以讓我們在選取時就能先判斷。
舉例而言,假設在欄位`role`中的資料是字串,內容長成這樣 1,2,3,6,8,12,14,15,21,22,25,....99
我希望取出欄位 `role` 中如果有數字 2 的資料,如果用這種方法取用,也許會取回我要的資料,但如果 2 在第一筆或最後一筆,就會取不到資料:
再如果把 ',' 拿掉,則含有 2, 12, 21, 22, 25... 的資料都會被取出:
所以用like沒辦法正確的取出我們要的資料,這時正規表達式就派上用場,只是mysql的正規表達式比較怪異!
正則表達式語法
REGEXP + '正則表達式字串'
ex: 以數字2結尾
SELECT * FROM `table` WHERE `role` REGEXP '2$'
上式等同於
SELECT * FROM `table` WHERE `role` like '%2'
這樣子還是取不出單一個數字 2 的結果,這時就要用到mysql的邊界符號:
[[:<:]] 和 [[:>:]] 是MySQL 的邊界符號,分別代表左和右邊界,邊界的定義和 perl 的 \b 類似,只要 2 的左右邊界:
都不是1數字、2字母或3_ 就符合
因此上式改為:
就能取出正確的結果。
以分類比對
mysql也定義了一些常用的字元分類(posix格式)[3],稱之為 character class,其中有定義一些字元的群組:
字元分類名稱 | 定義 |
---|---|
alnum | A-Za-z0-9 注意不包含底線'_' |
alpha | A-Za-z_ 不含數字 |
blank |
空白、\t |
cntrl | 控制字元 \x00-\x1F及\x7F |
digit | 0-9 |
graph | 我認為是拿來作base64圖形會用到的字元 \x21-\x7E,不含空白。 這些字元也是能顯示的字元(非控制字元) |
lower | a-z |
同graph但多了一個空白 | |
punct | 符號 !"\#$%&'()*+, \-./:;<=>?@\[ \\\]^_`{|}~ |
space | 空白、\t、\r、\n 這四個,\v, \f這兩個不確定,mysql官網沒寫到 註:\t=tab, \r=回到行首, \n=換行, \v=ctrl+K, \f=form_feed=\x12 |
upper | A-Z |
xdigit | 0-9, a-f, A-F |
使用時把名稱包在 [:分類名稱:] 即可。
舉例而言,數字0-9就是[:digit:],換句話說 [:digit:] 只是代表 "0-9"
假如要比對所有的數字,還得用"[ ]"給包起來:
select "12345" regexp "[:digit:]+" =>0 錯誤
select "12345" regexp "[[:digit:]]+" =>1 正確
特殊字符
有些特殊字符在mysql中是用[.和.]這個包起來表示
例如反斜線 '\' [.backslash.]
TAB鍵 [.tab.]
中括號的右邊 ']' [.right-square-bracket.]
其他更多定義的特殊字符,請參考[2]
範例
ex1: 字串'justalnums'是否全由A-Za-z_組成
結果1
ex2. 字串'justalnums'是否全由A-Za-z_組成
結果0
ex3. 字串"123\\12324" 是否由全數字和反斜線組成
結果1
ex4. 比對一個`range`欄位帶有括號的數字,如"(12)", "(0)" 比對成功;"(不是數字)", "(0a)" 比對失敗
ex5. 比對email格式
ex6. 比對電話號碼是否為 (數字)數字或連字號'-' 所組成,但字尾不得為 '-'
mysql的regexp比較其實很陽春,只能比對個大概
ex7. 字串開頭是 0-9A-F連著一個點 '.',注意點的寫法不是\.而是[.]請參考[4],\. 在mysql中還是會被當成「任一個字元」
參考資料
[1] http://www.tech-recipes.com/rx/484/use-regular-expressions-in-mysql-select-statements/
[2] Mysql 特殊符號的比對 https://dev.mysql.com/doc/refman/5.7/en/regexp.html
[3] http://www.regular-expressions.info/posixbrackets.html
[4] https://stackoverflow.com/questions/18153898/whole-word-matching-with-dot-characters-in-mysql