文章目錄
- chapter 4 檢索資料--select 語句
- chapter 5 排序檢索資料--order by子句
- chapter 6 過濾資料--where子句
- chapter 7 過濾資料--where子句高階用法
- chapter 8 用通配符進行過濾
- chapter 9 用正規表達式進行搜尋
-
- 9.1 正規表達式介紹
- 9.2 使用MySQL正規表達式
-
- 9.2.1 基本字元比對
-
- like與regexp的差別
- 9.2.2 OR比對
- 9.2.3 比對幾個字元之一
- 9.2.4 比對範圍
- 9.2.5 比對特殊字元
- 9.2.6 比對特殊字元
- 9.2.7 比對多個執行個體
- 9.2.8 定位符
-
- 簡單的正規表達式測試
chapter 4 檢索資料–select 語句
select prod_name from products;--檢索單列
select prod_id,prod_name from products;--檢索多列
select * from products;--檢索所有列
select distinct prod_id from products;--檢索不同行
select prod_name from products limit 5;--限制結果,傳回前5行(索引[0,4])
select prod_name from products limit 5,5;--限制結果,傳回第二個5行(索引[5,9]),第一個數為開始位置,第二個數為檢索行數
select products.prod_name from products;--使用完全限定的名字來引用列
select products.prod_name from database_name.products;--使用完全限定的名字來引用表
limit 用法的補充說明
- 行0:檢索出來的第一行為行0,而不是行1,是以limit 1,1将傳回第二行。
- 行數不夠時:如limit 10,5 而實際中隻有13行,那麼MySQL隻傳回能傳回的行數。
-
offset:limit 4 offset 3 意為從行3(索引為3的行,實際中的第4行)開始取4行。
也就是說下面兩種寫法是等價的。
select * from salaries
limit 3,4;
select * from salaries
limit 4 offset 3;
chapter 5 排序檢索資料–order by子句
select 出的資料如果不排序,資料一般以它在底層表中的出現順序顯示,可以使資料最初添加到表中的順序。但是如果資料之後經過更新或删除,則此順序會受到MySQL重用回收存儲空間的影響。
是以,如果不明确控制的話,不能(也不應該)依賴該排序順序。
select prod_name
from products
order by prod_name--以prod_name列字母順序排序
select prod_name
from products
order by prod_id,prod_name--以多個列排序,先按id,再按名字
select prod_name
from products
order by prod_id desc,prod_name asc --以多個列排序,先按id降序,再按名字升序
chapter 6 過濾資料–where子句
資料庫表中包含大量資料,很少需要檢索表中所有行。通常會根據需求提取資料的子集。
隻檢索所需資料需要制定搜尋條件(search criteria),搜尋條件也稱為過濾條件(filter condition)。
select prod_name,prod_price
from products
where prod_price=2.50--where過濾條件,單值
order by prod_id
select prod_name,prod_price
from products
where prod_price between 5 and 10--where過濾條件,範圍
select prod_name,prod_price
from products
where prod_price is NULL--where過濾條件,空值檢查
--NULL值與0,空字元串或空格 不同
操作符 | 說明 |
= | 等于 |
<>、!= | 不等于 |
< | 小于 |
<= | 小于等于 |
> | 大于 |
>= | 大于等于 |
between | 在兩個值之間(閉區間) |
chapter 7 過濾資料–where子句高階用法
操作符(operator):用來聯結或改變where子句中的子句的關鍵字。也稱邏輯操作符(logical operator)。
select prod_id,prod_name,prod_price
from products
where prod_id=1003 and prod_price<=10 --AND操作符
select prod_id,prod_name,prod_price
from products
where prod_id=1002 or prod_id=1003 --OR操作符
select prod_id,prod_name,prod_price
from products
where prod_id=1002 or prod_id=1003 and prod_price<=10 --計算次序:目标找出10元以下且由1002或1003組成的産品
--該查詢不能滿足要求,因為SQL優先處理AND,再處理OR
--該查詢結果為1003的價格低于10的産品 或者1002的産品無論價格如何
--解決方案:加括号
select prod_id,prod_name,prod_price
from products
where (prod_id=1002 or prod_id=1003) and prod_price<=10
--括号的另一種用法:in操作符來制定條件範圍
select prod_id,prod_name,prod_price
from products
where prod_id in (1002,1003)--IN操作符 相當于 OR
為什麼要用IN操作符
- 使用較長的合法選項清單時,IN操作符更清晰直覺;
- 計算的次序更容易管理;
- IN操作符一般比OR操作符執行快;
- IN操作符最大優點——可以包含其他的select語句,建立更動态的where子句。
--NOT操作符:否定它之後的任何條件
select prod_id,prod_name,prod_price
from products
where prod_id not in (1002,1003)--NOT操作符
為什麼要用NOT操作符
- 複雜情況下與in連用
- MySQL 的NOT 支援與IN / BETWEEN / EXISTS子句取反。
chapter 8 用通配符進行過濾
之前涉及的操作符(operator)【and,or,not,in】都是對已知值進行過濾的。無論是單值、多值,或者檢查某個範圍,使用的值都是已知的。但這種方法不是任何時候的好用。
比如,怎麼搜尋産品名中包含文本‘anvil’的所有産品?
通配符(wildcard):用來比對值的一部分的特殊字元。本身是SQL的where子句中有特殊含義的字元,使用時必須搭配like操作符。
搜尋模式(search pattern):由字面值、通配符或兩者組合構成的搜尋條件。
操作符何時不是操作符?
答案是:當它作為謂詞時。從技術上說like是謂詞而不是操作符。
百分号(%)通配符
select prod_id,prod_name
from products
where prod_name like 'jet%'--百分号(%)通配符,表示任何字元出現任意次數,此處意為找出是以以jet開頭的産品
--區分大小寫,此與JetPack不比對
select prod_id,prod_name
from products
where prod_name like '%jet%'--通配符可以在搜尋模式中的任意位置使用,并且可以使用多個通配符,此處%位于模式的兩端,表示比對任何位置包含文本jet的值,無論前後出現什麼
select prod_id,prod_name
from products
where prod_name like 'j%t'--通配符可以在搜尋模式中的任意位置使用
% 能比對0個、1個或多個字元
但是有一個例外——NULL
即使是where prod_name like ‘%’ 也不能比對NULL
下劃線(_)通配符
下劃線(_)通配符的用途與%一樣,但是隻能比對 1 個字元,而不是多個。
select prod_id,prod_name
from products
where prod_name like '_ ton anvil' --比對到的結果有
--1 ton anvil
--2 ton anvil
select prod_id,prod_name
from products
where prod_name like '% ton anvil' --比對到的結果有
--.5 ton anvil
--1 ton anvil
--2 ton anvil
MySQL的通配符很有用,但是這種功能是有代價的:通配搜尋的處理時間一般比較長。
使用通配符的技巧:
- 不要過度使用通配符。如果其他操作符能達到同樣的結果,應使用其他的操作符。
- 除非絕對必要,否則不要把他們用在搜尋模式的最開始處。放在最開始處,搜尋起來是最慢的。
- 仔細注意通配符的位置。如果放錯,可能不會傳回想要的結果。
chapter 9 用正規表達式進行搜尋
where子句中使用正規表達式來更好地控制資料過濾。
更透徹的介紹:《正規表達式必知必會》
9.1 正規表達式介紹
前兩章中,過濾使用到比對、比較和通配操作符。對于基本的過濾,這樣足夠了。但是随着過濾複雜性的增加,where子句本身的複雜性也有必要增加。
正規表達式:用來比對文本的特殊的串(字元集合)。
9.2 使用MySQL正規表達式
9.2.1 基本字元比對
select prod_name
from products
where prod_name regexp '1000'
order by prod_name-- 除關鍵字 like 被 regexp 代替,這條語句非常像like語句
--此意為:regexp後面跟的東西作為正規表達式處理(與文字正文1000比對的一個正規表達式)
--傳回結果
--JetPack 1000
上例中,正規表達式并未帶來太多好處,可能還會降低性能,但是在複雜的實際場景中,它會發揮巨大的價值。如下例:
select prod_name
from products
where prod_name regexp '.000'
order by prod_name
--此處應用了正規表達式'.000','.'是正規表達式中一個特殊的字元,表示比對任意一個字元,是以1000和2000都比對傳回
--傳回結果
--JetPack 1000
--JetPack 2000
like與regexp的差別
select prod_name
from products
where prod_name like '1000'
order by prod_name;
--傳回結果
--不傳回資料
select prod_name
from products
where prod_name regexp '1000'
order by prod_name;
--傳回結果
--JetPack 1000
like比對整個列,如果被比對的文本在列值中出現,like不會找到它,相應的行也不會傳回(除非使用通配符)。
regexp在列值内進行比對,如果被比對的文本在列值中出現,regexp會找到它,相應的行将被傳回。
regexp能否用于比對整個列值(發揮與like相同的作用)?
可以,使用^和$定位符(anchor)即可。
9.2.2 OR比對
為搜尋兩個串之一(這個串,或另一個串),使用 | 。
select prod_name
from products
where prod_name regexp '1000|2000|3000'
order by prod_name;
--傳回結果
--JetPack 1000
--JetPack 2000
--JetPack 3000
9.2.3 比對幾個字元之一
比對任何單一字元。
如果隻想比對特定字元怎麼辦? 可通過指定一組用[和]括起來的字元來完成。
select prod_name
from products
where prod_name regexp '[123] Ton'
order by prod_name;
--regexp 對大小寫不敏感,且需要注意空格
--正規表達式[123]意為:比對1或2或3
--[] 是另一種形式的OR語句,[123]是[1|2|3]的縮寫
--[1|2|3] ton 的意思與1|2|3 ton 的意思不同,1|2|3 ton 表示1或2或3 ton
--字元集合也可以被否定
--正規表達式[^123]意為:比對除卻1/2/3這些字元外的任何東西
--傳回結果
--1 ton anvil
--2 ton anvil
--3 ton anvil
9.2.4 比對範圍
集合可用來定義要比對的1個或多個字元.
如
[0123456789]
可簡化為
[0-9]
.
同理,
[a-z]
比對任意字母字元。
select prod_name
from products
where prod_name regexp '[1-5] Ton'
order by prod_name;
--正規表達式'[1-5] Ton',[1-5]定義了一個範圍
--傳回結果
--.5 ton anvil
--1 ton anvil
--2 ton anvil
9.2.5 比對特殊字元
正規表達式語言由具有特定含義的特殊字元構成,如’.’、’[]’、‘|’、‘-’等。如果要比對’.’、’[]’、‘|’、‘-’這些字元,應該怎麼辦?
select vend_name
from vendors
where vend_name regexp '.'
order by vend_name
--此處每個行都被檢索出來,'.'比對任意字元
--為了比對特殊字元,必須用\\為前導,\\-表示查找-,\\.表示查找.
--傳回結果
--ACME
--Anvils R Us
--Furball Inc.
--Jet Set
--Jouets Et Ours
--LT Supplies
select vend_name
from vendors
where vend_name regexp '\\.'
order by vend_name
--這種處理就是所謂的轉義(escaping)
--傳回結果
--Furball Inc.
元字元 | 說明 |
\\f | 換頁 |
\\n | 換行 |
\\r | 回車 |
\ | 制表 |
\\v | 縱向制表 |
\\\ | 比對反斜杠\ |
9.2.6 比對特殊字元
為更友善工作,可以使用預定義的字元集,稱為字元類(character class)。
類 | 說明 |
[:alnum:] | 任意字母和數字(同[a-zA-Z0-9]) |
[:alpha:] | 任意字母(同[a-zA-Z]) |
[:blank:] | 空格和制表(同[\ ]) |
[:space:] | 空白在内的任意空白字元(同[\\f\\n\\r\ \\v]) |
[:cntrl:] | ASCII控制字元(ASCII0到31和127) |
[:digit:] | 任意數字(同[0-9]) |
[:print:] | 任意可列印字元 |
[:graph:] | 同[:print:],但不包括空格 |
[:lower:] | 任意小寫字母(同[a-z]) |
[:upper:] | 任意大寫字母(同[A-Z]) |
[:punct:] | 既不在[:alnum:],也不在[:cntrl:]中的任意字元 |
[:xdigit:] | 任意16進制數字(同[a-fA-F0-9]) |
9.2.7 比對多個執行個體
目前為止,所有正規表達式都試圖比對單詞出現。對于重複的情況,可以用重複元字元來完成。
重複元字元 | 說明 |
* | 0個或多個比對 |
+ | 1個或多個比對(同{1,}) |
? | 0個或1個比對(同{0,1}) |
{n} | 指定數目比對 |
{n,} | 不少于指定數目的比對 |
{n,m} | 比對數目的範圍(m<=255) |
select prod_name
from products
where prod_name regexp '\\([0-9] sticks?\\)'
order by prod_name
--傳回結果
--TNT (1 stick)
--TNT (5 sticks)
正規表達式’
\\([0-9] sticks?\\)'
\\(
比對
(
[0-9]
比對
任意數字
sticks?
比對
stick
或
sticks
因為
?
比對它前面的字元0次或1次
\\)
比對
)
select prod_name
from products
where prod_name regexp '[[:digit:]]{4}'
order by prod_name
--等價于
select prod_name
from products
where prod_name regexp '[0-9][0-9][0-9][0-9]'
order by prod_name
--傳回結果
--JetPack 1000
--JetPack 2000
正規表達式
'[[:digit:]]{4}'
[:digit:]
比對
任意數字
,是以它是數字的一個集合
{4}
确切地要求它前面的字元(任意數字)出現4次
是以在外層再套一層
[]
得到
[[:digit:]]
,最終比對連在一起的任意4位數字。
9.2.8 定位符
目前為止,所有正規表達式都是比對一個串中任意位置的文本。為了比對特定位置的文本,需要使用定位符。
元字元 | 說明 |
^ | 文本的開始 |
$ | 文本的結尾 |
[[:<:]] | 詞的開始 |
[[:>:]] | 詞的結尾 |
select prod_name
from products
where prod_name regexp '^[0-9\\.]'
order by prod_name
--傳回結果
--.5 ton anvil
--1 ton anvil
--2 ton anvil
正規表達式
'^[0-9\\.]'
^
隻在
.
或
任意數字
為串中第一個字元時才比對它們。如果沒有
^
,則還要多檢索出别的行,即那些中間有
數字
或
.
的行。
^
的雙重用途
(1)在集合中(用
定義),用它來否定該集合; (2)在集合外,用它來指串的開始處。
[和]
簡單的正規表達式測試
在不适用資料庫表的情況下(不用
from table_name
),直接用
select
來測試正規表達式。
regexp
總是傳回0(沒有比對)或1(比對)。
可以用帶文字串的
regexp
來測試表達式,并試驗它們。
select 'hello' regexp '[0-9]'
--因為hello中沒有數字,是以傳回0 (沒有比對)
--傳回結果
--0