1. 程式人生 > 程式設計 >Mysql中正則表示式Regexp常見用法

Mysql中正則表示式Regexp常見用法

Mysql中Regexp常見用法

模糊匹配,包含特定字串
# 查詢content欄位中包含“車友俱樂部”的記錄

select * from club_content where content regexp '車友俱樂部'

# 此時的regexp與like的以下用法是等同的

select * from club_content where content like '%車友俱樂部%'

模糊匹配,以特定字串開頭
# 查詢content欄位中以“車友”開頭的記錄

select * from club_content where content regexp '^車友'

# 此時的regexp與like的以下用法是等同的

select * from club_content where content like '車友%'

模糊匹配,以特定字串結尾
# 查詢content欄位中以“車友”結尾的記錄

select * from club_content where content regexp '車友$'

# 此時的regexp與like的以下用法是等同的

select * from club_content where content like '%車友'

模糊匹配,或關係
# 查詢content欄位中包含“心得”、“分享”或“技術貼”

select * from club_content where content REGEXP '心得|分享|技術貼'

模糊匹配,不包含單個字元
# 查詢content欄位中不包含“車”字、“友”字的記錄

select * from club_content where content REGEXP [^車友]

這個結果跑出來一看大吃一驚,竟然把所有記錄給跑出來,這是為什麼呢?
因為一旦加了這個方括號"[]",它就把裡面的內容拆成單個的字元再匹配,它會逐個字元去匹配判斷是不是等於“車”,或者是不是等於“友“,返回的結果是一組0、1的邏輯值。

如果想匹配不包含特定字串,該怎麼實現呢?

模糊匹配,不包含特定字串
# 查詢content欄位不包含“車友”字串的記錄

select * from club_content where content not REGEXP '車友'

MySql REGEXP運算子匹配字串

1 ^ 匹配以該字元後面的字元開頭的字串
舉個例子: REGEXP ‘^x' 表示匹配以x開頭的字元
2 $匹配以該字元前面的字元結尾的字串
舉個例子: REGEXP ‘y$' 表示匹配以y結尾的字元
3 .匹配任意一個字元
4 […]匹配在方括號中的任意一個字元。
如: [1-9] 匹配1到9的數字,[abc]匹配其中任意一個
5 *匹配零個或多個在它前面的字元
如: x* 匹配任何數量的x字元

mysql 如何判斷 "字串" 是否為 "數字"

這個問題有點怪,但很多時候我們會以字串的形式儲存數字,反過來我們用字串進行數學運算時,好像也不會出錯 . 除非,用作數學運算的字串不能轉換成數字 .
但是我們改如何判斷字串是否能轉換成數字呢 ?

採用mysql的 REGEXP運算子 . 怎麼用?

{String} REGEXP '[^0-9.]'

前面的字串是我們要做判斷的, 後面的字串是mysql的正則表示式,意思是 匹配不是數字或者小數點的字元。

如果String中含有不是0-9之間的數字或者是小數點時,返回true ,反之則返回false。

比如說 :

select ('123a' REGEXP '[^0-9.]'); --‘123a'中含有字元'a' 輸出結果為1 mysql中常量true輸出為1 false輸出為0

注意:如果字串中有空格,也會匹配到正則表示式,返回1。如果是要去掉兩端的空格,就要將判斷的字串,就要對字串使用 trim()函數了。

這個只是REGEXP操作符的簡單應用,REGEXP的詳細應用請參考官方文件。 

MySQL 正則表示式

在前面的章節我們已經瞭解到MySQL可以通過 LIKE ...% 來進行模糊匹配。

MySQL 同樣也支援其他正則表示式的匹配, MySQL中使用 REGEXP 操作符來進行正則表示式匹配。

如果您瞭解PHP或Perl,那麼操作起來就非常簡單,因為MySQL的正則表示式匹配與這些指令碼的類似。

下表中的正則模式可應用於 REGEXP 操作符中。

模式 描述
^ 匹配輸入字串的開始位置。如果設定了 RegExp 物件的 Multiline 屬性,^ 也匹配 '\n' 或 '\r' 之後的位置。
$ 匹配輸入字串的結束位置。如果設定了RegExp 物件的 Multiline 屬性,$ 也匹配 '\n' 或 '\r' 之前的位置。
. 匹配除 "\n" 之外的任何單個字元。要匹配包括 '\n' 在內的任何字元,請使用象 '[.\n]' 的模式。
[...] 字元集合。匹配所包含的任意一個字元。例如, '[abc]' 可以匹配 "plain" 中的 'a'。
[^...] 負值字元集合。匹配未包含的任意字元。例如, '[^abc]' 可以匹配 "plain" 中的'p'。
p1|p2|p3 匹配 p1 或 p2 或 p3。例如,'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 則匹配 "zood" 或 "food"。
* 匹配前面的子表示式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等價於{0,}。
+ 匹配前面的子表示式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等價於 {1,}。
{n} n 是一個非負整數。匹配確定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的兩個 o。
{n,m} m 和 n 均為非負整數,其中n <= m。最少匹配 n 次且最多匹配 m 次。

例項

瞭解以上的正則需求後,我們就可以根據自己的需求來編寫帶有正則表示式的SQL語句。以下我們將列出幾個小例項(表名:person_tbl )來加深我們的理解:

查詢name欄位中以'st'為開頭的所有資料:

mysql> SELECT name FROM person_tbl WHERE name REGEXP '^st';

查詢name欄位中以'ok'為結尾的所有資料:

mysql> SELECT name FROM person_tbl WHERE name REGEXP 'ok$';

查詢name欄位中包含'mar'字串的所有資料:

mysql> SELECT name FROM person_tbl WHERE name REGEXP 'mar';

查詢name欄位中以母音字元開頭或以'ok'字串結尾的所有資料:

mysql> SELECT name FROM person_tbl WHERE name REGEXP '^[aeiou]|ok$';

mysql正則REGEXP學習練習筆記

REGEXP在mysql是用來執行正則表示式的一個函式,像php中的preg之類的函數了,regexp正則函式如果只是簡單的查詢使用like即可,但複雜的還是需要使用regexp了,下面我們來看看。

MySql使用者手冊建議,在構造簡單查詢時,仍使用萬用字元。

如:

Select [*|fieldname list] From [tablename] where [fieldname] like ["%someletter"|"%someletter%","_","?someletter"];

但在一些特殊查詢中,不用正則表示式是不行的。MYSQL提供的正則表示式WHERE謂詞有三個,分別是:

REGEXP,RLIKE,NOT RLIKE

用這三個替換原有的LIKE謂詞,後面即可以跟正則表示式。
例如要查詢欄位中含有“_”的資料,則要用以下查詢語句:

SELECT * FROM TABLENAME WHERE FIELDNAME RLIKE '.[_].';

擴充套件正則表示式的一些字元是:

· ‘.'匹配任何單個的字元。
· 字元類“[...]”匹配在方括號內的任何字元。例如,“[abc]”匹配“a”、“b”或“c”。為了命名字元的範圍,使用一個“-”。“[a-z]”匹配任何字母,而“[0-9]”匹配任何數字。
· “ * ”匹配零個或多個在它前面的字元。例如,“x*”匹配任何數量的“x”字元,“[0-9]*”匹配任何數量的數字,而“.*”匹配任何數量的任何字元。
如果REGEXP模式與被測試值的任何地方匹配,模式就匹配(這不同於LIKE模式匹配,只有與整個值匹配,模式才匹配)。
為了定位一個模式以便它必須匹配被測試值的開始或結尾,在模式開始處使用“^”或在模式的結尾用“$”。
為了找出以“b”開頭的名字,使用“^”匹配名字的開始:
使用正則

SELECT * FROM pet WHERE name REGEXP BINARY ‘^b';
SELECT * FROM pet WHERE name REGEXP ‘fy$';
SELECT * FROM pet WHERE name REGEXP ‘w';
SELECT * FROM pet WHERE name REGEXP ‘^…..$';
SELECT * FROM pet WHERE name REGEXP ‘^.{5}$';

今天在應用中遇到了這樣的一個問題,

有一個欄位 t1,其中的值類似於:1,1,2,3,4,5,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. 使用LIKE和NOT LIKE比較操作符(注意不能使用=或!=);
2. 模式預設是忽略大小寫的;
3. 允許使用”_”匹配任何單個字元,”%”匹配任意數目字元(包括零字元);

附一些mysql正則規則

^ 匹配字串的開始部分
$ 匹配字串的結束部分
. 匹配任何字元(包括回車和新行)
a* 匹配0或多個a字元的任何序列
a+ 匹配1個或多個a字元的任何序列
a? 匹配0個或1個a字元
de|abc 匹配序列de或abc
(abc)* 匹配序列adc的0個或者多個例項

{n}、{m,n} {n}或{m,n}符號提供了編寫正則表示式的更通用方式,能夠匹配模式的很多前述原子(或“部分”)。m和n均為整數。
a* 可被寫為a{0,}
a+ 可被寫為a{1,}
a? 可被寫為a{0,1}

[a-dX] 匹配任何是a,b,c,d或者X的字元,兩個其他字元之間的'-'字元構成一個範圍
[^a-dX] 匹配任何不是a,d或者X的字元,前面的字元'^'是否定的意思

[.characters.] 在括號表示式中(使用[和]),匹配用於校對元素的字元序列,字元為單個字元或新行等字元名
mysql> SELECT ‘~' REGEXP ‘[[.~.]]'; -> 1
mysql> SELECT ‘~' REGEXP ‘[[.tilde.]]'; -> 1

[=character_class=]
在括號表示式中(使用[和]),[=character_class=]表示等同類。它與具有相同校對值的所有字元匹配,包括它本身,
[[=a=]] 等同於[a(+)],[a+],[a{1,}]

[:character_class:]
在括號表示式中(使用[和]),[:character_class:]表示與術語類的所有字元匹配的字元類。

標準的類名稱是:

alnum 文字數字字元
alpha 文字字元
blank 空白字元
cntrl 控制字元
digit 數字字元
graph 圖形字元
lower 小寫文字字元
print 圖形或空格字元
punct 標點字元
space 空格、製表符、新行、和回車
upper 大寫文字字元
xdigit 十六進位制數字字元

[[:<:]],[[:>:]]

這些標記表示word邊界。它們分別與word的開始和結束匹配。word是一系列字字元,其前面和後面均沒有字字元。字元是alnum類中的字母數字字元或下劃線(_)。

mysql> select ‘fang shan zi' regexp ‘[[:<:]]shan[[:>:]]'; -> 1
mysql> select ‘fang shan zi' regexp ‘[[:<:]]fang[[:>:]]'; -> 1
mysql> select ‘fang shans zi' regexp ‘[[:<:]]shan[[:>:]]'; -> 0

正則表示式使用特殊字元,應在其前面加上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

MySQL 查尋條件使用正則 regexp

我用的是 Mybatis

t.hobby : 條件欄位
hobby: 查尋引數,值可以是多個逗號分隔的值:‘閱讀,交友,圍棋'

<!-- t.hobby 的值最初可能是這樣: ' 吃,喝,嫖,賭,抽,坑,蒙,拐,騙,偷 ' 每個詞的兩邊有空格不規則 -->
<!-- 下面逐步演示 -->
<if test="hobby!=null and hobby!=''">
concat(',',REPLACE (t.hobby,' ',''),') regexp concat(',(',replace(#{hobby},'|'),'),')
</if>
<!-- 表字段 t.hobby 取出值 -->
<if test="hobby!=null and hobby!=''">
concat(',REPLACE (' 吃,偷 ',')
</if>
<!-- 表字段值處理後,去掉了多餘的空格 -->
<if test="hobby!=null and hobby!=''">
concat(','吃,偷',')
</if>
<!-- concat後得到一個字串,首尾加上了逗號 -->
<if test="hobby!=null and hobby!=''">
',吃,偷,' regexp concat(',')
</if>
<!-- 取出引數 #{hobby} 的值 -->
<if test="hobby!=null and hobby!=''">
',replace('吃,嫖',')
</if>
<!-- 把逗號換成 | -->
<if test="hobby!=null and hobby!=''">
','吃|喝|嫖|嫖',')
</if>
<!-- concat後得到一個字串,首尾加上了括號,逗號 -->
<if test="hobby!=null and hobby!=''">
',' regexp ',(吃|喝|嫖|嫖),' <!-- 紀念于謙老師不賭的美德 -->
</if>

得到結果是 1 作為條件就是真了。

複雜的過程主要是用來處理查尋條件。得到符合要求的正則作條件就ok了
但個人覺得,更理想的方式是:
被查尋欄位在當初存入資料時就處理好格式:'吃,偷'
查尋條件可以處理好傳進來:','
那麼一個查尋就可以簡化成這樣

<if test="hobby!=null and hobby!=''">
concat(',t.hobby,') regexp #{hobby}
</if>

到這就差不多了,基本上就可以看得懂了,實在不行就參考下面的相關文章。