天天看點

mysql正則通配符全解_MySQL模糊查詢用法大全(正則、通配符、内置函數等)

SELECT * from table where username like '%陳哈哈%' and hobby like '%牛逼'

這是一條我們在MySQL中常用到的模糊查詢方法,通過通配符%來進行比對,其實,這隻是冰山一角,在MySQL中,支援模糊比對的方法有很多,且各有各的優點。好了,今天讓我帶大家一起掀起MySQL的小裙子,看一看模糊查詢下面還藏着多少鮮為人知的好東西。

一、MySQL通配符模糊查詢(%,_)

1-1. 通配符的分類"%" 百分号通配符: 表示任何字元出現任意次數 (可以是0次)。

"_" 下劃線通配符:表示隻能比對單個字元,不能多也不能少,就是一個字元。當然,也可以like "陳____",數量不限。

like操作符:LIKE作用是訓示mysql後面的搜尋模式是利用通配符而不是直接相等比對進行比較;但如果like後面沒出現通配符,則在SQL執行優化時将 like 預設為 “=”執行意: 如果在使用like操作符時,後面沒有使用通用比對符(%或_),那麼效果是和“=”一緻的。在SQL執行優化時查詢優化器将 like 預設為 “=”執行,SELECT * FROM movies WHERE movie_name like '唐伯虎';隻能比對movie_name=“唐伯虎”的結果,而不能比對像“唐伯虎點秋香”或“唐伯虎點香煙”這樣的結果.

1-2. 通配符的使用

1) % 通配符:

-- 模糊比對含有“網”字的資料

SELECT * from app_info where appName like '%網%';

-- 模糊比對以“網”字結尾的資料

SELECT * from app_info where appName like '%網';

-- 模糊比對以“網”字開頭的資料

SELECT * from app_info where appName like '網%';

-- 精準比對,appName like '網' 等同于:appName = '網'

SELECT * from app_info where appName = '網';

-- 等同于

SELECT * from app_info where appName like '網';

-- 模糊比對含有“xxx網xxx車xxx”的資料,如:"途途網約車司機端、網絡約車平台"

SELECT * from app_info where appName like '%網%車%';

2) _ 通配符:

-- 查詢以“網”為結尾的,長度為三個字的資料,如:"鍊家網",

SELECT * from app_info where appName like '__網';

-- 模糊比對含有“xx網x車xxx”的資料,如:"攜程網約車用戶端"

SELECT * from app_info where appName like '__網_車%';

注意事項:注意大小寫,在使用模糊比對時,也就是比對文本時,MySQL預設配置是不區分大小寫的。當你使用别人的MySQL資料庫時,要注意是否區分大小寫,是否區分大小寫取決于使用者對MySQL的配置方式.如果是區分大小寫,那麼像Test12這樣記錄是不能被"test__"這樣的比對條件比對的。

注意尾部空格,"%test"是不能比對"test "這樣的記錄的。

注意NULL,%通配符可以比對任意字元,但是不能比對NULL,也就是說SELECT * FROM blog where title_name like '%';是比對不到title_name為NULL的的記錄。

1-3. 技巧與建議:

正如所見,MySQL的通配符很有用。但這種功能是有代價的:通配符搜尋的處理一般要比前面讨論的其他搜尋所花時間更長,消耗更多的記憶體等資源。這裡給出一些使用通配符要記住的技巧。不要過度使用通配符。如果其他操作符能達到相同的目的,應該使用其他操作符。

在确實需要使用通配符時,除非絕對有必要,否則不要把它們用在搜尋模式的開始處。因為MySQL在where後面的執行順序是從左往右執行的,如果把通配符置于搜尋模式的開始處(最左側),搜尋起來是最慢的(因為要對全庫進行掃描)。

仔細注意通配符的位置。如果放錯地方,可能不會傳回想要的資料。

有細心地朋友會發現,如果資料中有“%”、“_”等符号,那豈不是和通配符沖突了?

SELECT * from app_info where appName LIKE '%%%';

SELECT * from app_info where appName LIKE '%_%';

确實如此,上面面兩條SQL語句查詢的都是全表資料,而不是帶有"%"和"_"的指定資料。這裡需要加 ESCAPE 關鍵字進行轉義。

如下,ESCAPE 後面跟着一個字元,裡面寫着什麼,MySQL就把那個符号當做轉義符,一般我就寫成"/";然後就像 C語言中轉義字元一樣 例如 ‘\n’,’\t’, 把這個字元寫在你需要轉義的那個%号前就可以了;

SELECT * from app_info where appName LIKE '%/_%' ESCAPE '/';

但是這種情況有沒有更高端點的解決辦法呢?能讓檢查你代碼的同僚或上司對你刮目相看那種~~

當然,下面我們就來看看MySQL的第二類模糊比對方式 --- 内置函數查詢

二、MySQL内置函數檢索(locate,position,instr)

話接上文,通過内置函數locate,position,instr進行比對,相當于Java中的str.contains()方法,傳回的是比對内容在字元串中的位置,效率和可用性上都優于通配符比對。

SELECT * from app_info where INSTR(`appName`, '%') > 0;

SELECT * from app_info where LOCATE('%', `appName`) > 0;

SELECT * from app_info where POSITION( '%' IN `appName`) > 0;

如上,三種内置函數預設都是:> 0,是以下列 > 0 可加可不加,加上可讀性更好。

OK,下面一起來看看這三種内置函數的使用方法吧。

先明确一下,MySQL中的角标從左往右是從1開始的,不像java最左邊第一位角标是0,是以在MySQL中角标為0時說明不存在。

2-1. LOCATE()函數文法: LOCATE(substr,str)

傳回 substr 在 str 中第一次出現的位置。如果 substr 在 str 中不存在,傳回值為 0,如果substr 在 str 中存在,傳回值為:substr 在 str中第一次出現的位置。

注意:LOCATE(substr,str)與 POSITION(substr IN str)是同義詞,功能相同。文法: LOCATE(substr, str, [pos])

從位置pos開始的字元串str中第一次出現子字元串substr的位置。 如果substr不在str中,則傳回0。 如果substr或str為NULL,則傳回NULL。

SELECT locate('a', 'banana'); -- 2

SELECT locate('a', 'banana', 3); -- 4

SELECT locate('z', 'banana'); -- 0

SELECT locate(10, 'banana'); -- 0

SELECT locate(NULL , 'banana'); -- null

SELECT locate('a' , NULL ); -- null

執行個體:

-- 用LOCATE關鍵字進行模糊比對,等同于:"like '%網%'"

SELECT * from app_info where LOCATE('網', `appName`) > 0;

-- 用LOCATE關鍵字進行模糊比對, 從第二個字元開始比對"網",則"網易雲遊戲、網來商家"等資料就被過濾了

SELECT * from app_info where LOCATE('網', `appName`, 2) > 0;

2-2. POSITION()方法文法:POSITION(substr IN substr)

這個方法可以了解為locate(substr,str)方法的别名,因為它和locate(substr,str)方法的作用是一樣的。

執行個體:

-- 用POSITION關鍵字進行模糊比對,等同于:"like '%網%'"

SELECT * from app_info where POSITION( '網' IN `appName`);

2-3. INSTR()方法文法: INSTR(str,substr)

傳回字元串str中第一次出現子字元串substr的位置。INSTR()與LOCATE()的雙參數形式相同,隻是參數的順序相反。

執行個體:

-- 用INSTR關鍵字進行模糊比對,功能跟like一樣 ,等同于:"like '%網%'"

SELECT * from app_info where INSTR(`appName`, '網');

-- instr函數作用,一般用于檢索某字元在某字元串中的位置,等同于:"like '%網%'"

SELECT * from app_info where INSTR(`appName`, '網') > 0;

三、MySQL基于regexp、rlike的正則比對查詢

MySQL中的regexp和rlike關鍵字屬于同義詞,功能相同。本文以regexp為準。

REGEXP 不支援通配符"%、_",支援正則比對規則,是一種更細力度且優雅的比對方式,一起來看看吧

-- 這裡給出regexp包含的參數類型

-- REGEXP '網' 等同于 like '%網%'

SELECT * from app_info where appName REGEXP '網';

-- 等同于

SELECT * from app_info where appName like '%網%';

3-1. regexp中的 OR : |

功能:可以搜尋多個字元串之一,相當于 or

-- 支援 "|" ‘或’符号,比對包含“中國”或“網際網路”或“大學”的資料,支援疊加多個

SELECT * from app_info where appName REGEXP '中國|網際網路|大學';

-- 比對同時命中“中國”、“網”的資料可以用".+"連接配接,代表中國xxxx網,中間允許有任意個字元,順序不能反。

SELECT * from app_info where appName REGEXP '中國.+網';

3-2. REGEXP中的正則比對 : []

功能:比對[]符号中幾個字元之一,支援解析正規表達式

-- 比對包含英文字元的資料,預設不區分大小寫情況下

SELECT * from app_info where appName REGEXP '[a-z]';

-- 跟like一樣,取反集加 "not REGEXP" 即可,下面不再贅述

SELECT * from app_info where appName not REGEXP '[a-z]';

-- 比對包含大寫英文字元的資料,預設忽略大小寫,需要加上"BINARY"關鍵字。如where appName REGEXP BINARY 'Hello'-- 關于大小寫的區分:MySQL中正規表達式比對(從版本3.23.4後)不區分大小寫 。

SELECT * from app_info where appName REGEXP BINARY '[A-Z]';

-- 比對包含數字的資料

SELECT * from app_info where appName REGEXP '[0-9]';

-- 比對包含數字或英文的資料,

SELECT * from app_info where appName REGEXP '[a-z0-9]';

a-z、0-9都認定為一個機關,不要加多餘符号,前兩天就發現了一個特殊情況,很有意思的bug,跟他家分享一下

-- 之前寫查詢語句時多加了"|"符号,以為是"或",沒有在意,但萬萬沒想到,查出數量竟不同

SELECT * from app_info where appName REGEXP '[567]'; -- 87條

SELECT * from app_info where appName REGEXP '[5|6|7]'; -- 88條

一頭霧水,趕快看看差得是哪一條

-- 原來"|"符号也參與到了比對中,認定為一個機關。巧的是有一個資料為:“無線調音台 | Wireless Mixer” 這個正好比對上。卧槽了個DJ

SELECT * from app_info where appName REGEXP '[5|6|7]' and pid not in (SELECT pid from app_info where appName REGEXP '[567]');

-- 查詢以5、6、7其中一個為開頭的資料

SELECT * from app_info where appName REGEXP '^[5|6|7]';溫馨提示:MySQL中,UTF-8的中文=3個位元組;GBK的中文=2個位元組

-- 查詢appName位元組長度為10,任意内容的資料

SELECT * from app_info where appName REGEXP '^.{10}$';

- 查詢appName位元組長度為10,且都為大寫英文的資料,加上BINARY即可

SELECT * from app_info where appName REGEXP BINARY '^[A-Z]{10}$';

-- 查詢version_name位元組長度為6,且都為數字或"." 的資料

SELECT * from app_info where version_name REGEXP '^[0-9.]{6}$';

-- 查詢version_name位元組長度為6,且都為數字或"." 的資料;要求首位為1,末位為7

SELECT * from app_info where version_name REGEXP '^1[0-9.]{4}7$' ;

-- 查詢version_name位元組長度為6位以上,且都為數字或"." 的資料;要求首位為1,末位為7

SELECT * from app_info where version_name REGEXP '^1[0-9.]{4,}7$' ;

-- 查詢version_name位元組長度為 6 - 8 位,且都為數字或"." 的資料;要求首位為1,末位為7

SELECT * from app_info where version_name REGEXP '^1[0-9.]{4,6}7$' ;

-- 首位字元不是中文的

SELECT * from app_info where appName REGEXP '^[ -~]';

-- 首位字元是中文的

SELECT * from app_info where appName REGEXP '^[^ -~]';

-- 查詢不包含中文的資料

SELECT * from app_info where appName REGEXP '^([a-z]|[0-9]|[A-Z])+$';

-- 以5或F開頭的,且包含英文的資料

SELECT * from app_info where appName REGEXP BINARY '^[5F][a-zA-Z].';

特殊符号的比對,例如.,需要加\\(注意是兩個斜杠),但是如果在[]中可以不加:

-- 比對name中含有.的

select * from app_info where appName regexp '\\.';

-- 比對name中含有.的

select * from app_info where appName regexp '[.]';

3-3. 字元類比對(posix)

mysql中有一些特殊含義的符号,可以代表不同類型的比對:

-- 比對name中含有數字的

select * from app_info where appName regexp '[[:digit:]]';

其他的這種字元類還有:

這種字元類需要主要的外層要加一層[]。

3-4. [:<:>:]

上面的字元類中有兩個比較特殊的,這兩個是關于位置的,[:<:>:]比對詞的結束,它們和 ^、$ 不同。

後者是比對整個整體的開頭和結束,而前者是比對一個單詞的開始和結束。

-- 隻能比對整體以a開頭的,例如abcd

select * from app_info where appName regexp '^a';

-- 能比對整體以a開頭的,也能比對中間的單詞以a開頭,如:dance after。

select * from app_info where appName regexp '[[:<: src="data:image/svg+xml;utf8,<svg%20xmlns='http://www.w3.org/2000/svg'%20width='459'%20height='191'></svg>">

[[:<:>:]] 分别比對一個單詞開頭和結尾的空的字元串,這個單詞開頭和結尾都不是包含在alnum中的字元也不能是下劃線。

select "a word a" REGEXP "[[:<:>:]]"; -- 1(表示比對)

select "a xword a" REGEXP "[[:<:>:]]"; -- 0(表示不比對)

select "weeknights" REGEXP "^(wee|week)(knights|nights)$"; -- 1(表示比對)

四、總結

好啦,本篇文章就到這裡了,能看到這裡的都是有緣人,希望本文能幫助到你對MySQL的了解更進一步。請不要吝啬手中的贊呦。謝謝支援!