天天看點

【資料庫筆記】MySQL必知必會:chapter 4-9 檢索/排序/過濾資料 select語句 | order by 子句| where子句 | 通配符過濾 | 正規表達式過濾chapter 4 檢索資料–select 語句chapter 5 排序檢索資料–order by子句chapter 6 過濾資料–where子句chapter 7 過濾資料–where子句高階用法chapter 8 用通配符進行過濾chapter 9 用正規表達式進行搜尋

文章目錄

  • 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操作符
  1. 使用較長的合法選項清單時,IN操作符更清晰直覺;
  2. 計算的次序更容易管理;
  3. IN操作符一般比OR操作符執行快;
  4. IN操作符最大優點——可以包含其他的select語句,建立更動态的where子句。
--NOT操作符:否定它之後的任何條件
select prod_id,prod_name,prod_price
from products
where prod_id not in (1002,1003)--NOT操作符
           
為什麼要用NOT操作符
  1. 複雜情況下與in連用
  2. 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
           

繼續閱讀