本文主要介紹如何在Mysql中使用正則表達式進行搜索。html
正則表達式是一個很是大的內容,我會在以後專門寫博客介紹,這裏只是簡介一些經常使用匹配模式git
博客文章地址:http://weiya.me/item/59.html正則表達式
以前幾篇文章講解了各類各樣的過濾數據條件,經過這些條件,咱們已經可以知足平常開發中大部分的工做。但假設篩選條件更加複雜一點,好比你的老闆叫你從郵箱+手機號碼混合註冊的用戶中找出手機號碼註冊用戶,要給他們發送營銷短信。這時,以前的過濾方法就不太奏效。正則表達式搜索就派上大用場。sql
簡單來講,正則表達式就是用來匹配文本的特殊字符串。好比,從文本中提取電話號碼,帶數字的用戶名,或者提取某個特定格式的文本。數據庫
並且全部語言編輯器基本上都支持正則表達式,不得不說,正則表達式已經成爲開發過程當中強大而有力的工具。Mysql也不例外,那麼就開始正式學習這種特殊匹配方式。編程
本文所用到的Mysql表在文章最後的附錄。segmentfault
匹配字符串是正則表達式最基礎的應用。咱們先給出一個例子:咱們從一個用戶表中查詢出名字中包含有100數字的用戶編程語言
SELECT * FROM my_user WHERE `name` REGEXP '100';
咱們獲得了用戶ID爲1的用戶:小紅100編輯器
該語句中不一樣於以前的語句,咱們使用REGEXP
關鍵字表明後面爲正則表達式工具
這條語句看起來和LIKE
語句特別類似,並且也是可使用LIKE
語句來實現。那使用正則表達式的意義何在?
緣由很簡單。假設,我如今須要匹配不只僅是包含100數字的用戶,而是100,200,或者300,只要是整百的都須要匹配。或者說,我須要全部名字裏麪包含數字的,不管什麼數字。那麼使用LIKE
來實現就會顯得十分的困難。而正則表達式就會顯得十分簡單。
SELECT * FROM my_user WHERE `name` REGEXP '.00'; // 匹配包含整百的名字,如100,200,300等等
表達式.00
裏面的點,表明的任意字符。也就是不管是1仍是2仍是9,或者是字母什麼的均可以匹配,匹配任意。
SELECT * FROM my_user WHERE `name` REGEXP '[0-9]'; // 匹配全部名字裏麪包含數字的用戶
是否是來的比LIKE
簡單得多?上面的表達式,咱們在接下來就會詳細闡述。
那麼咱們什麼狀況下應該使用LIKE
?什麼狀況下又適合使用正則表達式查詢?
這裏咱們只須要記住LIKE
查詢和正則查詢很是重要的差異便可。
先看兩個例子:
一、以前的一條語句
SELECT * FROM my_user WHERE `name` REGEXP '100';
二、LIKE
查詢的實現
SELECT * FROM my_user WHERE `name` LIKE '100';
這裏咱們能夠清楚的看到二者的區別:正則表達式返回了一條記錄,而LIKE
查詢沒有匹配到任何記錄
結論:LIKE
查詢匹配整個列,若是須要匹配的字符串(好比上面的100)包含在列中,那麼則沒法匹配成功。而正則匹配則能夠匹配列值內部的值,簡單來講就是它會從第一個字符開始日後匹配,只要匹配有一個成功那麼就會返回記錄。這是二者重要的區別。
那麼正則匹配是否也能夠匹配整個字符,固然能夠。不過須要涉及到另外的知識:定位符^
和$
,下面將會做詳細解釋。
若是正則表達式僅僅就是和LIKE
有那麼一點兒的差異,也就不會有這麼高的地位了。下面纔是顯示身手的時候。
或查詢也叫OR
查詢,是條件並列查詢的一種狀況。相似於編程語言裏面的if else
只要有一個條件符合就會被匹配。
SELECT * FROM my_user WHERE `name` REGEXP '100|200';
上面的語句查詢了名字中包含了100或者200數字的用戶,就是說兩個數值只要匹配一個就能夠返回數據。
固然你也能夠給出多個或狀況,他們之間使用豎線分割便可。好比:100|200|300|400
使用或查詢的狀況,有點兒相似於SELECT
中使用OR
條件鏈接的狀況,你能夠把它們想象成併入了一個正則表達式。
正則匹配中有一種特殊的OR
匹配。
SELECT * FROM my_user WHERE `name` REGEXP '[12]';
上面表達式中咱們使用了一個特殊的字符串[12]
,這個字符串的含義是:查詢名字中包含有數字1或者數字2的記錄,它是[1|2]
的縮寫。
這種,使用方括號將字符串括起來的寫法,不管方括號內有多少字符串,其表達的含義都是匹配其中任意一個。
若是是[123456789]那麼就表明,匹配名字中包含1或2或3或4或5或6或7或8或9的任何一個記錄。
固然,字符串還能夠查詢被否認的狀況。[^12]
若是在12以前加上一個^
符號,那麼就表明除了1或2外的字符串。
SELECT * FROM my_user WHERE `name` REGEXP '[^12]';
說明:表中小紅100,雖然包含1,可是他包含了0。0不屬於1或者2,因此被匹配。
看下咱們上面有個集合[123456789],若是每次咱們寫正則時候都這麼寫,那麼豈不是很麻煩。因此,咱們能夠簡化這種狀況,使用一個範圍[1-9]來代替這串字符串。若是是匹配全部數字,那麼就會包含0,咱們可使用[0-9]來表示。
SELECT * FROM my_user WHERE `name` REGEXP '[0-9]';
這個表達式將會匹配出全部名字中包含數字的記錄。拆開理解就是,包含0或者1或者2...或者8或者9的記錄。
並且,這裏的範圍不只僅只能是數字,還能夠是字母。好比[a-z]就是表示從字母a到字母z的全部數字,26個字母。小寫完了,還有大寫[A-Z]。那麼咱們將其組合起來[0-9a-zA-Z]這個表達式就十分強大了,能夠表示包含數字,小寫字母,大寫字母的全部記錄。
SELECT * FROM my_user WHERE `name` REGEXP '[0-9a-zA-Z]';
因爲我名字裏面沒有包含字母的,因此結果和上面[0-9]相同。
咱們來看下下面的一條語句:
SELECT * FROM my_user WHERE `name` REGEXP '[0-9]';
這個語句的意思是匹配名稱包含全部數字的記錄。0-9被方括號擴了起來,那麼假設我如今就須要匹配方闊號該如何處理?
這個時候就須要用到匹配特殊字符的知識。爲了匹配這些特殊的字符,咱們須要使用轉義功能,就是使用(雙反斜槓)做爲前導。假設咱們須要匹配經常使用特殊字符便可這麼寫:
\\[ 匹配左方括號 \\. 匹配點號 \\] 匹配右方括號 \\| 匹配豎線 \\\ 匹配反斜槓本身自己
依次類推,其餘特殊的字符串也可使用這麼方式處理。
雙反斜槓加上一些字母還能夠表示特殊的含義。
好比:
\\f 換頁 \\n 換行 \\r 回車 \\t 製表符 \\v 縱向製表符
在通常的編程語言中,轉義通常使用一個反斜線,在Mysql中爲何是兩個才行?緣由是:Mysql本身須要一個來識別,而後Mysql會將扣除了一個反斜槓的剩餘的部分徹底的交給正則表達式庫解釋,因此加起來就是兩個了。
雖然正則表達式提供了一些很長表示方式的縮寫,好比[0-9]表示數字。[a-z]表示小寫字母。可是,有些時候仍是以爲複雜。因此,正則表達式還提供了一些預約義的字符類來方便咱們開發。
簡單來講,就像車牌使用蘇表明江蘇,而滬表明上海同樣。
咱們直接給出表直接參閱。
類 | 說明 |
---|---|
[:alnum:] | 任意數字和字母。至關於[a-zA-Z0-9] |
[:alpha:] | 任意字符。至關於[a-zA-z] |
[:blank:] | 空格和製表。至關於[(雙斜槓,segmentfault這裏雙斜槓打不出來)t] |
[:cntrl:] | ASCII控制字符(ASCII 0 到31和127) |
[:digit:] | 任意數字。至關於[0-9] |
[:graph:] | 與[:print:]相同,可是不包含空格 |
[:lower:] | 任意的小寫字母。至關於[a-z] |
[:print:] | 任意可打印字符 |
[:punct:] | 既不在[:alnum:]又不在[:cntrl:]中的任意字符 |
[:space:] | 包括空格在內的任意空白字符。 |
[:upper:] | 任意大寫字母。至關於[A-Z] |
[:xdigit:] | 任意十六進制的數字。至關於[a-fA-F0-9] |
以前匹配的內容都是單詞匹配。就是若是匹配到一次就顯示,匹配不到就不顯示。可是,複雜的狀況有時候要求匹配不止一次。假設我須要匹配名字中包含2-3位數字的記錄。這個時候就須要使用一種特殊的元字符來修飾。
SELECT * FROM my_user WHERE `name` REGEXP '[0-9]{2,3}';
是否是很是簡單?下面具體解釋它的用法。
拿出這個特殊字符串[0-9]{2,3}
,除去前面的[0-9]
後面的{2,3}
就被成爲重複元字符,它的做用就是使得前面的數字重複必定的次數。
元字符 | 做用 |
---|---|
* | 重複0次或者屢次 |
+ | 重複一次或者屢次。至關於{1,} |
? | 重複0次或者1次 |
{n} | 重複n次 |
{n,} | 重複至少n次 |
{n,m} | 重複n-m次 |
SELECT * FROM my_user WHERE `name` REGEXP '[0-9]*'; // 匹配名字包含或者不包含數字的記錄
SELECT * FROM my_user WHERE `name` REGEXP '[0-9]{2,3}'; // 匹配名字內包含2位數或者3位數的記錄
除了以前的重複元字符,正則還有一種特殊的定位元字符
元字符 | 做用 |
---|---|
^ | 文本開始 |
$ | 文本結尾 |
[[:<:]] | 詞的開始 |
[[:>:]] | 詞的結尾 |
還記得以前區別LIKE
和正則表達式的例子麼?LIKE
是對整個字符串進行匹配,而正則是匹配到就能夠。
若是如今咱們須要在郵箱+手機號碼混合註冊的帳號中,挑選出手機號碼,那麼咱們就要對帳號進行從頭至尾的匹配。
好比手機號碼是11位數字,也就是說a11111111111不行,可是他又具有11個數字條件。
因此咱們要求從頭開始匹配到結尾,是11位數字。
SELECT * FROM my_user WHERE `name` REGEXP '^[0-9]{11}$';
爲了匹配到內容,我在數據庫內又加了一條記錄。
匹配結果
SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for my_user -- ---------------------------- DROP TABLE IF EXISTS `my_user`; CREATE TABLE `my_user` ( `user_id` int(11) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(30) NOT NULL, `age` tinyint(2) NOT NULL DEFAULT '0', `password` varchar(40) NOT NULL, `code` varchar(10) DEFAULT NULL, PRIMARY KEY (`user_id`) ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of my_user -- ---------------------------- INSERT INTO `my_user` VALUES ('1', '小紅100', '20', '7c4a8d09ca3762af61e59520943dc26494f8941b', '2arfs5dr6m'); INSERT INTO `my_user` VALUES ('2', '小明200', '19', '7c4a8d09ca3762af61e59520943dc26494f8941b', 'd59tg6dr5h'); INSERT INTO `my_user` VALUES ('3', '小黃350', '25', '7c4a8d09ca3762af61e59520943dc26494f8941b', 'w56tg9hjn3'); INSERT INTO `my_user` VALUES ('4', '小穎410', '25', '7c4a8d09ca3762af61e59520943dc26494f8941b', 'a5d23e9yh5'); INSERT INTO `my_user` VALUES ('5', '星空幻穎', '22', '7c4a8d09ca3762af61e59520943dc26494f8941b', '86d2sadft9');
星空幻穎,嚴穎
我的主頁:segmentfault