mysql where子句的模式匹配
今天在應用中遇到了這樣的一個問題,
有一個字段 t1,其中的值相似於:1,1,1,2,3,3,4,4,5,5,2,4,3,2,1,2
須要從裏面搜索出好比說:第一個逗號前的數字範圍爲3-5之間,第三個逗號前的數字的範圍爲3-5之間,第10個逗號前的數字範圍爲3-5之間,其他的都爲1-5之間。。。
則sql語句能夠這麼寫:
SELECT * FROM tb WHERE t1 REGEXP '^[3-5],[1-5],[3-5],[1-5],[1-5],[1-5],[1-5],[1-5],[1-5],[3-5],[1-5],[1-5],[1-5],[1-5],[1-5],[1-5]%';
1. 使用LIKE和NOT LIKE比較操做符(注意不能使用=或!=);
2. 模式默認是忽略大小寫的;
3. 容許使用」_」匹配任何單個字符,」%」匹配任意數目字符(包括零字符);
MySQL還提供象UNIX實用程序的擴展正則表達式模式匹配的格式:
1. 使用REGEXP和NOT REGEXP操做符(或RLIKE和NOT RLIKE,他們是同義詞);
2. REGEXP模式匹配與被匹配字符的任何地方匹配,則匹配成功(即只要被匹配字符包含或者能夠等於所定義的模式,就匹配成功);
不一樣於LIKE模式匹配,只有和整個值匹配,才匹配成功(即只有被匹配字符徹底和所定義的模式匹配,才匹配成功)
3. REGEXP默認也是不區分大小寫,可使用BINARY關鍵詞強制區分大小寫;
如:SELECT * FROM pet WHERE name REGEXP BINARY ‘^B’;
4. 正則表達式爲一個表達式,它可以描述一組字符串。REGEXP操做符完成MySQL的擴展正則表達式匹配。REGEXP實現的功能是若是被匹配字符中部分或徹底符合所定義的表達式描述的字符,則表示匹配成功。
1)最簡單的正則表達式是不含任何特殊字符的正則表達式,如hello。
SELECT * FROM pet WHERE name REGEXP ‘hello’;表示的意思是若是name這列的某一行包含hello這個單詞,則匹配就成功了。(注意和LIKE的區別,LIKE要求name這列的某一行必須徹底等於hello,才匹配成功)。
2)非平凡的正則表達式,除了含有最簡單表達式那些東西,還須要採用特殊的特殊結構,用到的字符,往下看。(所以,一般的正則表達式是普通單詞和這些正則表達式字符構成的表達式)
5. 擴展正則表達式的一些字符:
1) ‘.’匹配任何單個字符;
2) […]匹配在方括號內的任何字符,可使用’-’表示範圍,如[a-z],[0-9],並且能夠混合[a-dXYZ]表示匹配a,b,c,d,X,Y,Z中的任何一個;(注意使用括號以及’|’的方法也能夠達到相同的效果,如(a|b|c)匹配a,b,c中的任何一個);此外可使用’^’表示否認,如[^a-z]表示不含有a-z中間的任何一個字符;
3) ‘*’表示匹配0個或多個在它前面的字符。如x*表示0個或多個x字符,.*表示匹配任何數量的任何字符;
4) 能夠將模式定位必須匹配被匹配字符的開始或結尾,在匹配模式前加」^」:表示匹配從被匹配字符的最開頭開始,在匹配模式後加」$」:表示匹配要進行到被匹配字符的最末尾。
5) ‘+’表示匹配1個或多個在它前面的字符。如a+表示1個或多個a字符。
6) ‘?’表示匹配0個或1個在它前面的字符。如a?表示0個或1個a字符。
7) ‘|’如de|abc表示匹配序列de或者abc。注意雖然[…]也能夠表示匹配中的某一個,可是每次僅僅能表示單個字符及[a-bXYZ]實際每一次只表明了一個字符。
8) ()括號能夠應用在表達式中,使得更容易理解。
9) a{5}表示匹配共5個a,a{2,8}表示匹配2~8個a。
a*能夠寫成a{0, } 第二個參數省略表示沒有上界;a+能夠寫成a{1,};a?能夠寫成a{0,1}
更準確地講,a{n}與a的n個實例準確匹配。a{n,}匹配a的n個或更多實例。a{m,n}匹配a的m~n個實例,包含m和n
m和n必須位於0~RE_DUP_MAX(默認爲255)的範圍內,包含0和RE_DUP_MAX。若是同時給定了m和n,m必須小於或等於n。
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->
10) 標準類別[:character_class:]:
經常使用的一些標準類別,通常在[]中使用,因爲用在[]中故和[a-z]相似,每一次只能頂替一個字符。(這個有點相似perl裏面定義的經常使用的一些標準類別:\w表示一個單詞字符即[a-zA-Z0-9];\W一個非單詞字符與\w相反; \d一個數字即[0-9];\D一個非數字;\s一個白空間字符即[\t\f\r\n];\f爲換頁符;\S一個非白空間字符)
標準的類別名稱:
alnum
文字數字字符
alpha
文字字符
blank
空白字符
cntrl
控制字符
digit
數字字符
graph
圖形字符
lower
小寫文字字符
print
圖形或空格字符
punct
標點字符
space
空格、製表符、新行、和回車
upper
大寫文字字符
xdigit
十六進制數字字符
使用實例:
SELECT 'justalnums' REGEXP '[[:alnum:]]+';
解釋其中[[:alnum:]]因爲[:alnum:]表示文字數字字符,它又用在[]中,故[[:alnum:]]表明一個字符它爲一個文字或者數字。後面的+號表示1個或多個這樣的文字或數字。
上述語句返回1.那是由於justalnums中是由字母組成的。
11)字邊界:[[:<:]]表示開始,[[:>:]]表示結束:
其定義了一個單詞的開始和結束邊界,這個單詞爲字字符,這樣[[:<:]]表明這個字字符前面的部分,[[:>:]]表明這個字字符後面的部分。字字符爲alnum類的字母數字字符或下劃線(_);所以[[:<:]], [[:>:]]均表明不是字字符的字符,即只要不是字母數字字符以及下劃線(_)便可。所以其能夠爲何都不是。所以[[:<:]]word[[:>:]]可以匹配以下的全部狀況:
即word單詞自己,word*** 解釋***表明不是字母數字以及_的任何字符(如,word-net);***word(如,micorsoft word);***word***(如,this is a word program.)
舉例:[[:<:]]word[[:>:]]:
SELECT 'a word a' REGEXP '[[:<:]]word[[:>:]]'; 結果爲真
SELECT 'a xword a' REGEXP '[[:<:]]word[[:>:]]'; 結果爲假
最後注意的注意:
要在正則表達式中使用特殊字符,須要在這些字符前面添加2個反斜槓’\’,
舉例:
SELECT '1+2' REGEXP '1+2'; 結果爲0
SELECT '1+2' REGEXP '1\+2'; 結果爲0
SELECT '1+2' REGEXP '1\\+2'; 結果爲1
解釋:
這是由於MySQL解析程序解析該SQL語句時:
首先將字符串’1\\+2’解析爲1\+2;
而後把1\+2看成正則表達式,由正則表達式庫來解析,它表明1+2。
所以須要加上2個反斜槓。
不要常常犯加一個反斜槓的錯誤,加一個反斜槓會莫名其妙:
如SELECT '1t2' REGEXP '1\t2';
結果會返回1
原本的意思是匹配1製表符\t以及2,可是因爲只添加了一個\因此,解析之後編程了1t2,因此匹配成功。
12)
[.characters.]和[=character_class=]
附錄G:MySQL正則表達式
正則表達式是爲複雜搜索指定模式的強大方式。
MySQL採用Henry Spencer的正則表達式實施,其目標是符合POSIX 1003.2。請參見附錄C:感謝。MySQL採用了擴展的版本,以支持在SQL語句中與REGEXP操做符一塊兒使用的模式匹配操做。請參見3.3.4.7節,「模式匹配」。
在本附錄中,概括了在MySQL中可用於REGEXP操做的特殊字符和結構,並給出了一些示例。本附錄未包含可在Henry Spencer的regex(7)手冊頁面中發現的全部細節。該手冊頁面包含在MySQL源碼分發版中,位於regex目錄下的regex.7文件中。
正則表達式描述了一組字符串。最簡單的正則表達式是不含任何特殊字符的正則表達式。例如,正則表達式hello匹配hello。
非平凡的正則表達式採用了特殊的特定結構,從而使得它們可以與1個以上的字符串匹配。例如,正則表達式hello|word匹配字符串hello或字符串word。
做爲一個更爲複雜的示例,正則表達式B[an]*s匹配下述字符串中的任何一個:Bananas,Baaaaas,Bs,以及以B開始、以s結束、並在其中包含任意數目a或n字符的任何其餘字符串。
對於REGEXP操做符,正則表達式可使用任何下述特殊字符和結構:
· ^
匹配字符串的開始部分。
mysql> SELECT 'fo\nfo' REGEXP '^fo$'; -> 0
mysql> SELECT 'fofo' REGEXP '^fo'; -> 1
· $
匹配字符串的結束部分。
mysql> SELECT 'fo\no' REGEXP '^fo\no$'; -> 1
mysql> SELECT 'fo\no' REGEXP '^fo$'; -> 0
· .
匹配任何字符(包括回車和新行)。
mysql> SELECT 'fofo' REGEXP '^f.*$'; -> 1
mysql> SELECT 'fo\r\nfo' REGEXP '^f.*$'; -> 1
· a*
匹配0或多個a字符的任何序列。
mysql> SELECT 'Ban' REGEXP '^Ba*n'; -> 1
mysql> SELECT 'Baaan' REGEXP '^Ba*n'; -> 1
mysql> SELECT 'Bn' REGEXP '^Ba*n'; -> 1
· a+
匹配1個或多個a字符的任何序列。
mysql> SELECT 'Ban' REGEXP '^Ba+n'; -> 1
mysql> SELECT 'Bn' REGEXP '^Ba+n'; -> 0
· a?
匹配0個或1個a字符。
mysql> SELECT 'Bn' REGEXP '^Ba?n'; -> 1
mysql> SELECT 'Ban' REGEXP '^Ba?n'; -> 1
mysql> SELECT 'Baan' REGEXP '^Ba?n'; -> 0
· de|abc
匹配序列de或abc。
mysql> SELECT 'pi' REGEXP 'pi|apa'; -> 1
mysql> SELECT 'axe' REGEXP 'pi|apa'; -> 0
mysql> SELECT 'apa' REGEXP 'pi|apa'; -> 1
mysql> SELECT 'apa' REGEXP '^(pi|apa)$'; -> 1
mysql> SELECT 'pi' REGEXP '^(pi|apa)$'; -> 1
mysql> SELECT 'pix' REGEXP '^(pi|apa)$'; -> 0
· (abc)*
匹配序列abc的0個或多個實例。
mysql> SELECT 'pi' REGEXP '^(pi)*$'; -> 1
mysql> SELECT 'pip' REGEXP '^(pi)*$'; -> 0
mysql> SELECT 'pipi' REGEXP '^(pi)*$'; -> 1
· {1}, {2,3}
{n}或{m,n}符號提供了編寫正則表達式的更通用方式,可以匹配模式的不少前述原子(或「部分」)。m和n均爲整數。
o a*
可被寫入爲a{0,}。
o a+
可被寫入爲a{1,}。
o a?
可被寫入爲a{0,1}。
更準確地講,a{n}與a的n個實例準確匹配。a{n,}匹配a的n個或更多實例。a{m,n}匹配a的m~n個實例,包含m和n。
m和n必須位於0~RE_DUP_MAX(默認爲255)的範圍內,包含0和RE_DUP_MAX。若是同時給定了m和n,m必須小於或等於n。
mysql> SELECT 'abcde' REGEXP 'a[bcd]{2}e'; -> 0
mysql> SELECT 'abcde' REGEXP 'a[bcd]{3}e'; -> 1
mysql> SELECT 'abcde' REGEXP 'a[bcd]{1,10}e'; -> 1
· [a-dX], [^a-dX]
匹配任何是(或不是,若是使用^的話)a、b、c、d或X的字符。兩個其餘字符之間的「-」字符構成一個範圍,與從第1個字符開始到第2個字符之間的全部字符匹配。例如,[0-9]匹配任何十進制數字。要想包含文字字符「]」,它必須緊跟在開括號「[」以後。要想包含文字字符「-」,它必須首先或最後寫入。對於[]對內未定義任何特殊含義的任何字符,僅與其自己匹配。
mysql> SELECT 'aXbc' REGEXP '[a-dXYZ]'; -> 1
mysql> SELECT 'aXbc' REGEXP '^[a-dXYZ]$'; -> 0
mysql> SELECT 'aXbc' REGEXP '^[a-dXYZ]+$'; -> 1
mysql> SELECT 'aXbc' REGEXP '^[^a-dXYZ]+$'; -> 0
mysql> SELECT 'gheis' REGEXP '^[^a-dXYZ]+$'; -> 1
mysql> SELECT 'gheisa' REGEXP '^[^a-dXYZ]+$'; -> 0
· [.characters.]
在括號表達式中(使用[和]),匹配用於校對元素的字符序列。字符爲單個字符或諸如新行等字符名。在文件regexp/cname.h中,可找到字符名稱的完整列表。
mysql> SELECT '~' REGEXP '[[.~.]]'; -> 1
mysql> SELECT '~' REGEXP '[[.tilde.]]'; -> 1
· [=character_class=]
在括號表達式中(使用[和]),[=character_class=]表示等同類。它與具備相同校對值的全部字符匹配,包括它自己,例如,若是o和(+)均是等同類的成員,那麼[[=o=]]、[[=(+)=]]和[o(+)]是同義詞。等同類不得用做範圍的端點。
· [:character_class:]
在括號表達式中(使用[和]),[:character_class:]表示與術語類的全部字符匹配的字符類。標準的類名稱是:
alnum
文字數字字符
alpha
文字字符
blank
空白字符
cntrl
控制字符
digit
數字字符
graph
圖形字符
lower
小寫文字字符
print
圖形或空格字符
punct
標點字符
space
空格、製表符、新行、和回車
upper
大寫文字字符
xdigit
十六進制數字字符
它們表明在ctype(3)手冊頁面中定義的字符類。特定地區可能會提供其餘類名。字符類不得用做範圍的端點。
mysql> SELECT 'justalnums' REGEXP '[[:alnum:]]+'; -> 1
mysql> SELECT '!!' REGEXP '[[:alnum:]]+'; -> 0
· [[:<:]], [[:>:]]
這些標記表示word邊界。它們分別與word的開始和結束匹配。word是一系列字字符,其前面和後面均沒有字字符。字字符是alnum類中的字母數字字符或下劃線(_)。
mysql> SELECT 'a word a' REGEXP '[[:<:]]word[[:>:]]'; -> 1
mysql> SELECT 'a xword a' REGEXP '[[:<:]]word[[:>:]]'; -> 0
要想在正則表達式中使用特殊字符的文字實例,應在其前面加上2個反斜槓「\」字符。MySQL解析程序負責解釋其中一個,正則表達式庫負責解釋另外一個。例如,要想與包含特殊字符「+」的字符串「1+2」匹配,在下面的正則表達式中,只有最後一個是正確的:
mysql> SELECT '1+2' REGEXP '1+2'; -> 0
mysql> SELECT '1+2' REGEXP '1\+2'; -> 0
mysql> SELECT '1+2' REGEXP '1\\+2'; -> 1
引自:http://blog.sina.com.cn/s/blog_560bf765010096a6.htmlhtml