MySQL入門(mén)教程5 —— 從數(shù)據(jù)表中檢索信息
SELECT語(yǔ)句用來(lái)從數(shù)據(jù)表中檢索信息。語(yǔ)句的一般格式是:
SELECT what_to_select FROM which_table WHERE conditions_to_satisfy;
what_to_select指出你想要看到的內(nèi)容,可以是列的一個(gè)表,或*表示“所有的列”。which_table指出你想要從其檢索數(shù)據(jù)的表。WHERE子句是可選項(xiàng),如果選擇該項(xiàng),conditions_to_satisfy指定行必須滿(mǎn)足的檢索條件。
1. 選擇所有數(shù)據(jù)SELECT最簡(jiǎn)單的形式是從一個(gè)表中檢索所有記錄:
mysql> SELECT * FROM pet; +----------+--------+---------+------+------------+------------+| name | owner | species | sex | birth | death |+----------+--------+---------+------+------------+------------+| Fluffy | Harold | cat | f | 1993-02-04 | NULL || Claws | Gwen | cat | m | 1994-03-17 | NULL || Buffy | Harold | dog | f | 1989-05-13 | NULL || Fang | Benny | dog | m | 1990-08-27 | NULL || Bowser | Diane | dog | m | 1979-08-31 | 1995-07-29 || Chirpy | Gwen | bird | f | 1998-09-11 | NULL || Whistler | Gwen | bird | NULL | 1997-12-09 | NULL || Slim | Benny | snake | m | 1996-04-29 | NULL || Puffball | Diane | hamster | f | 1999-03-30 | NULL |+----------+--------+---------+------+------------+------------+
如果你想要瀏覽整個(gè)表,可以使用這種形式的SELECT,例如,剛剛裝載了初始數(shù)據(jù)集以后。也有可能你想到Bowser的生日看起來(lái)不很對(duì)。查閱你原來(lái)的家譜,你發(fā)現(xiàn)正確的出生年是1989,而不是1979。
至少有兩種修正方法:
·編輯文件“pet.txt”改正錯(cuò)誤,然后使用DELETE和LOAD DATA清空并重新裝載表:
mysql> DELETE FROM pet; mysql> LOAD DATA LOCAL INFILE ’pet.txt’ INTO TABLE pet;
然而, 如果這樣操做,必須重新輸入Puffball記錄。
·用一個(gè)UPDATE語(yǔ)句僅修正錯(cuò)誤記錄:
mysql> UPDATE pet SET birth = ’1989-08-31’ WHERE name = ’Bowser’;
UPDATE只更改有問(wèn)題的記錄,不需要重新裝載數(shù)據(jù)庫(kù)表。
2. 選擇特殊行如上所示,檢索整個(gè)表是容易的。只需要從SELECT語(yǔ)句中刪掉WHERE子句。但是一般你不想看到整個(gè)表,特別地當(dāng)表變得很大時(shí)。相反,你通常對(duì)回答一個(gè)具體的問(wèn)題更感興趣,在這種情況下在你想要的信息上進(jìn)行一些限制。讓我們看一些他們回答的有關(guān)你寵物的問(wèn)題的選擇查詢(xún)。可以從表中只選擇特定的行。例如,如果你想要驗(yàn)證你對(duì)Bowser的生日所做的更改,按下述方法選擇Bowser的記錄:
mysql> SELECT * FROM pet WHERE name = ’Bowser’; +--------+-------+---------+------+------------+------------+| name | owner | species | sex | birth | death |+--------+-------+---------+------+------------+------------+| Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 |+--------+-------+---------+------+------------+------------+
輸出證實(shí)正確的年份記錄為1989,而不是1979。
字符串比較時(shí)通常對(duì)大小些不敏感,因此你可以將名字指定為'bowser'、'BOWSER'等,查詢(xún)結(jié)果相同。
你可以在任何列上指定條件,不只僅僅是name。例如,如果你想要知道哪個(gè)動(dòng)物在1998以后出生的,測(cè)試birth列:
mysql> SELECT * FROM pet WHERE birth > ’1998-1-1’; +----------+-------+---------+------+------------+-------+| name | owner | species | sex | birth | death |+----------+-------+---------+------+------------+-------+| Chirpy | Gwen | bird | f | 1998-09-11 | NULL || Puffball | Diane | hamster | f | 1999-03-30 | NULL |+----------+-------+---------+------+------------+-------+
可以組合條件,例如,找出雌性的狗:
mysql> SELECT * FROM pet WHERE species = ’dog’ AND sex = ’f’;
+-------+--------+---------+------+------------+-------+| name | owner | species | sex | birth | death |+-------+--------+---------+------+------------+-------+| Buffy | Harold | dog | f | 1989-05-13 | NULL |+-------+--------+---------+------+------------+-------+
上面的查詢(xún)使用AND邏輯操作符,也有一個(gè)OR操作符:
mysql> SELECT * FROM pet WHERE species = ’snake’ OR species = ’bird’; +----------+-------+---------+------+------------+-------+| name | owner | species | sex | birth | death |+----------+-------+---------+------+------------+-------+| Chirpy | Gwen | bird | f | 1998-09-11 | NULL || Whistler | Gwen | bird | NULL | 1997-12-09 | NULL || Slim | Benny | snake | m | 1996-04-29 | NULL |+----------+-------+---------+------+------------+-------+
AND和OR可以混用,但AND比OR具有更高的優(yōu)先級(jí)。如果你使用兩個(gè)操作符,使用圓括號(hào)指明如何對(duì)條件進(jìn)行分組是一個(gè)好主意:
mysql> SELECT * FROM pet WHERE (species = ’cat’ AND sex = ’m’) -> OR (species = ’dog’ AND sex = ’f’); +-------+--------+---------+------+------------+-------+| name | owner | species | sex | birth | death |+-------+--------+---------+------+------------+-------+| Claws | Gwen | cat | m | 1994-03-17 | NULL || Buffy | Harold | dog | f | 1989-05-13 | NULL |+-------+--------+---------+------+------------+-------+3. 選擇特殊列
如果你不想看到表中的所有行,就命名你感興趣的列,用逗號(hào)分開(kāi)。例如,如果你想要知道你的動(dòng)物什么時(shí)候出生的,選擇name和birth列:
mysql> SELECT name, birth FROM pet; +----------+------------+| name | birth |+----------+------------+| Fluffy | 1993-02-04 || Claws | 1994-03-17 || Buffy | 1989-05-13 || Fang | 1990-08-27 || Bowser | 1989-08-31 || Chirpy | 1998-09-11 || Whistler | 1997-12-09 || Slim | 1996-04-29 || Puffball | 1999-03-30 |+----------+------------+
找出誰(shuí)擁有寵物,使用這個(gè)查詢(xún):
mysql> SELECT owner FROM pet; +--------+| owner |+--------+| Harold || Gwen || Harold || Benny || Diane || Gwen || Gwen || Benny || Diane |+--------+
請(qǐng)注意該查詢(xún)只是簡(jiǎn)單地檢索每個(gè)記錄的owner列,并且他們中的一些出現(xiàn)多次。為了使輸出減到最少,增加關(guān)鍵字DISTINCT檢索出每個(gè)唯一的輸出記錄:
mysql> SELECT DISTINCT owner FROM pet; +--------+| owner |+--------+| Benny || Diane || Gwen || Harold |+--------+
可以使用一個(gè)WHERE子句結(jié)合行選擇與列選擇。例如,要想查詢(xún)狗和貓的出生日期,使用這個(gè)查詢(xún):
mysql> SELECT name, species, birth FROM pet -> WHERE species = ’dog’ OR species = ’cat’; +--------+---------+------------+| name | species | birth |+--------+---------+------------+| Fluffy | cat | 1993-02-04 || Claws | cat | 1994-03-17 || Buffy | dog | 1989-05-13 || Fang | dog | 1990-08-27 || Bowser | dog | 1989-08-31 |+--------+---------+------------+4. 分類(lèi)行
你可能已經(jīng)注意到前面的例子中結(jié)果行沒(méi)有以特定的順序顯示。然而,當(dāng)行按某種方式排序時(shí),檢查查詢(xún)輸出通常更容易。為了排序結(jié)果,使用ORDER BY子句。這里是動(dòng)物生日,按日期排序:
mysql> SELECT name, birth FROM pet ORDER BY birth; +----------+------------+| name | birth |+----------+------------+| Buffy | 1989-05-13 || Bowser | 1989-08-31 || Fang | 1990-08-27 || Fluffy | 1993-02-04 || Claws | 1994-03-17 || Slim | 1996-04-29 || Whistler | 1997-12-09 || Chirpy | 1998-09-11 || Puffball | 1999-03-30 |+----------+------------+
在字符類(lèi)型列上,與所有其他比較操作類(lèi)似,分類(lèi)功能正常情況下是以區(qū)分大小寫(xiě)的方式執(zhí)行的。這意味著,對(duì)于等同但大小寫(xiě)不同的列,并未定義其順序。對(duì)于某一列,可以使用BINARY強(qiáng)制執(zhí)行區(qū)分大小寫(xiě)的分類(lèi)功能,如:ORDER BY BINARY col_name.
默認(rèn)排序是升序,最小的值在第一。要想以降序排序,在你正在排序的列名上增加DESC(降序 )關(guān)鍵字:
mysql> SELECT name, birth FROM pet ORDER BY birth DESC; +----------+------------+| name | birth |+----------+------------+| Puffball | 1999-03-30 || Chirpy | 1998-09-11 || Whistler | 1997-12-09 || Slim | 1996-04-29 || Claws | 1994-03-17 || Fluffy | 1993-02-04 || Fang | 1990-08-27 || Bowser | 1989-08-31 || Buffy | 1989-05-13 |+----------+------------+
可以對(duì)多個(gè)列進(jìn)行排序,并且可以按不同的方向?qū)Σ煌牧羞M(jìn)行排序。例如,按升序?qū)?dòng)物的種類(lèi)進(jìn)行排序,然后按降序根據(jù)生日對(duì)各動(dòng)物種類(lèi)進(jìn)行排序(最年輕的動(dòng)物在最前面),使用下列查詢(xún):
mysql> SELECT name, species, birth FROM pet -> ORDER BY species, birth DESC; +----------+---------+------------+| name | species | birth |+----------+---------+------------+| Chirpy | bird | 1998-09-11 || Whistler | bird | 1997-12-09 || Claws | cat | 1994-03-17 || Fluffy | cat | 1993-02-04 || Fang | dog | 1990-08-27 || Bowser | dog | 1989-08-31 || Buffy | dog | 1989-05-13 || Puffball | hamster | 1999-03-30 || Slim | snake | 1996-04-29 |+----------+---------+------------+
注意DESC關(guān)鍵字僅適用于在它前面的列名(birth);不影響species列的排序順序。
5. 日期計(jì)算MySQL提供了幾個(gè)函數(shù),可以用來(lái)計(jì)算日期,例如,計(jì)算年齡或提取日期部分。
要想確定每個(gè)寵物有多大,可以計(jì)算當(dāng)前日期的年和出生日期之間的差。如果當(dāng)前日期的日歷年比出生日期早,則減去一年。以下查詢(xún)顯示了每個(gè)寵物的出生日期、當(dāng)前日期和年齡數(shù)值的年數(shù)字。
mysql> SELECT name, birth, CURDATE(), -> (YEAR(CURDATE())-YEAR(birth)) -> - (RIGHT(CURDATE(),5)<RIGHT(birth,5)) -> AS age -> FROM pet; +----------+------------+------------+------+| name | birth | CURDATE() | age |+----------+------------+------------+------+| Fluffy | 1993-02-04 | 2003-08-19 | 10 || Claws | 1994-03-17 | 2003-08-19 | 9 || Buffy | 1989-05-13 | 2003-08-19 | 14 || Fang | 1990-08-27 | 2003-08-19 | 12 || Bowser | 1989-08-31 | 2003-08-19 | 13 || Chirpy | 1998-09-11 | 2003-08-19 | 4 || Whistler | 1997-12-09 | 2003-08-19 | 5 || Slim | 1996-04-29 | 2003-08-19 | 7 || Puffball | 1999-03-30 | 2003-08-19 | 4 |+----------+------------+------------+------+
此處,YEAR()提取日期的年部分,RIGHT()提取日期的MM-DD (日歷年)部分的最右面5個(gè)字符。比較MM-DD值的表達(dá)式部分的值一般為1或0,如果CURDATE()的年比birth的年早,則年份應(yīng)減去1。整個(gè)表達(dá)式有些難懂,使用alias (age)來(lái)使輸出的列標(biāo)記更有意義。
盡管查詢(xún)可行,如果以某個(gè)順序排列行,則能更容易地瀏覽結(jié)果。添加ORDER BY name子句按照名字對(duì)輸出進(jìn)行排序則能夠?qū)崿F(xiàn)。
mysql> SELECT name, birth, CURDATE(), -> (YEAR(CURDATE())-YEAR(birth)) -> - (RIGHT(CURDATE(),5)<RIGHT(birth,5)) -> AS age
-> FROM pet ORDER BY name;+----------+------------+------------+------+| name | birth | CURDATE() | age |+----------+------------+------------+------+| Bowser | 1989-08-31 | 2003-08-19 | 13 || Buffy | 1989-05-13 | 2003-08-19 | 14 || Chirpy | 1998-09-11 | 2003-08-19 | 4 || Claws | 1994-03-17 | 2003-08-19 | 9 || Fang | 1990-08-27 | 2003-08-19 | 12 || Fluffy | 1993-02-04 | 2003-08-19 | 10 || Puffball | 1999-03-30 | 2003-08-19 | 4 || Slim | 1996-04-29 | 2003-08-19 | 7 || Whistler | 1997-12-09 | 2003-08-19 | 5 |+----------+------------+------------+------+
為了按age而非name排序輸出,只要再使用一個(gè)ORDER BY子句:
mysql> SELECT name, birth, CURDATE(), -> (YEAR(CURDATE())-YEAR(birth)) -> - (RIGHT(CURDATE(),5)<RIGHT(birth,5)) -> AS age -> FROM pet ORDER BY age; +----------+------------+------------+------+| name | birth | CURDATE() | age |+----------+------------+------------+------+| Chirpy | 1998-09-11 | 2003-08-19 | 4 || Puffball | 1999-03-30 | 2003-08-19 | 4 || Whistler | 1997-12-09 | 2003-08-19 | 5 || Slim | 1996-04-29 | 2003-08-19 | 7 || Claws | 1994-03-17 | 2003-08-19 | 9 || Fluffy | 1993-02-04 | 2003-08-19 | 10 || Fang | 1990-08-27 | 2003-08-19 | 12 || Bowser | 1989-08-31 | 2003-08-19 | 13 || Buffy | 1989-05-13 | 2003-08-19 | 14 |+----------+------------+------------+------+
可以使用一個(gè)類(lèi)似的查詢(xún)來(lái)確定已經(jīng)死亡動(dòng)物的死亡年齡。你通過(guò)檢查death值是否是NULL來(lái)確定是哪些動(dòng)物,然后,對(duì)于那些非NULL值的動(dòng)物,需要計(jì)算出death和birth值之間的差:
mysql> SELECT name, birth, death, -> (YEAR(death)-YEAR(birth)) - (RIGHT(death,5)<RIGHT(birth,5)) -> AS age -> FROM pet WHERE death IS NOT NULL ORDER BY age; +--------+------------+------------+------+| name | birth | death | age |+--------+------------+------------+------+| Bowser | 1989-08-31 | 1995-07-29 | 5 |+--------+------------+------------+------+
查詢(xún)使用death IS NOT NULL而非death != NULL,因?yàn)镹ULL是特殊的值,不能使用普通比較符來(lái)比較,以后會(huì)給出解釋。
如果你想要知道哪個(gè)動(dòng)物下個(gè)月過(guò)生日,怎么辦?對(duì)于這類(lèi)計(jì)算,年和天是無(wú)關(guān)的,你只需要提取birth列的月份部分。MySQL提供幾個(gè)日期部分的提取函數(shù),例如YEAR( )、MONTH( )和DAYOFMONTH( )。在這里MONTH()是適合的函數(shù)。為了看它怎樣工作,運(yùn)行一個(gè)簡(jiǎn)單的查詢(xún),顯示birth和MONTH(birth)的值:
mysql> SELECT name, birth, MONTH(birth) FROM pet; +----------+------------+--------------+| name | birth | MONTH(birth) |+----------+------------+--------------+| Fluffy | 1993-02-04 | 2 || Claws | 1994-03-17 | 3 || Buffy | 1989-05-13 | 5 || Fang | 1990-08-27 | 8 || Bowser | 1989-08-31 | 8 || Chirpy | 1998-09-11 | 9 || Whistler | 1997-12-09 | 12 || Slim | 1996-04-29 | 4 || Puffball | 1999-03-30 | 3 |+----------+------------+--------------+
找出下個(gè)月生日的動(dòng)物也是容易的。假定當(dāng)前月是4月,那么月值是4,你可以找在5月出生的動(dòng)物 (5月),方法是:
mysql> SELECT name, birth FROM pet WHERE MONTH(birth) = 5; +-------+------------+| name | birth |+-------+------------+| Buffy | 1989-05-13 |+-------+------------+
如果當(dāng)前月份是12月,就有點(diǎn)復(fù)雜了。你不能只把1加到月份數(shù)(12)上并尋找在13月出生的動(dòng)物,因?yàn)闆](méi)有這樣的月份。相反,你應(yīng)尋找在1月出生的動(dòng)物(1月) 。
你甚至可以編寫(xiě)查詢(xún),不管當(dāng)前月份是什么它都能工作。采用這種方法不必在查詢(xún)中使用一個(gè)特定的月份,DATE_ADD( )允許在一個(gè)給定的日期上加上時(shí)間間隔。如果在NOW( )值上加上一個(gè)月,然后用MONTH()提取月份,結(jié)果產(chǎn)生生日所在月份:
mysql> SELECT name, birth FROM pet -> WHERE MONTH(birth) = MONTH(DATE_ADD(CURDATE(),INTERVAL 1 MONTH));
完成該任務(wù)的另一個(gè)方法是加1以得出當(dāng)前月份的下一個(gè)月(在使用取模函數(shù)(MOD)后,如果月份當(dāng)前值是12,則“回滾”到值0):
mysql> SELECT name, birth FROM pet -> WHERE MONTH(birth) = MOD(MONTH(CURDATE()), 12) + 1;
注意,MONTH返回在1和12之間的一個(gè)數(shù)字,且MOD(something,12)返回在0和11之間的一個(gè)數(shù)字,因此必須在MOD( )以后加1,否則我們將從11月( 11 )跳到1月(1)。
6. NULL值操作NULL值可能令人感到奇怪直到你習(xí)慣它。概念上,NULL意味著“沒(méi)有值”或“未知值”,且它被看作與眾不同的值。為了測(cè)試NULL,你不能使用算術(shù)比較 操作符例如=、<或!=。為了說(shuō)明它,試試下列查詢(xún):
mysql> SELECT 1 = NULL, 1 <> NULL, 1 < NULL, 1 > NULL; +----------+-----------+----------+----------+| 1 = NULL | 1 <> NULL | 1 < NULL | 1 > NULL |+----------+-----------+----------+----------+| NULL | NULL | NULL | NULL |+----------+-----------+----------+----------+
很顯然你不能通過(guò)這些比較得到有意義的結(jié)果。相反使用IS NULL和IS NOT NULL操作符:
mysql> SELECT 1 IS NULL, 1 IS NOT NULL; +-----------+---------------+| 1 IS NULL | 1 IS NOT NULL |+-----------+---------------+| 0 | 1 |+-----------+---------------+
請(qǐng)注意在MySQL中,0或 NULL意味著假而其它值意味著真。布爾運(yùn)算的默認(rèn)真值是1。
對(duì)NULL的特殊處理即是在前面的章節(jié)中,為了決定哪個(gè)動(dòng)物不再是活著的,使用death IS NOT NULL而不使用death != NULL的原因。
在GROUP BY中,兩個(gè)NULL值視為相同。
執(zhí)行ORDER BY時(shí),如果運(yùn)行 ORDER BY ... ASC,則NULL值出現(xiàn)在最前面,若運(yùn)行ORDER BY ... DESC,則NULL值出現(xiàn)在最后面。
NULL操作的常見(jiàn)錯(cuò)誤是不能在定義為NOT NULL的列內(nèi)插入0或空字符串,但事實(shí)并非如此。在NULL表示'沒(méi)有數(shù)值'的地方有數(shù)值。使用IS [NOT] NULL則可以很容易地進(jìn)行測(cè)試,如下所示:
mysql> SELECT 0 IS NULL, 0 IS NOT NULL, ’’ IS NULL, ’’ IS NOT NULL; +-----------+---------------+------------+----------------+| 0 IS NULL | 0 IS NOT NULL | ’’ IS NULL | ’’ IS NOT NULL |+-----------+---------------+------------+----------------+| 0 | 1 | 0 | 1 |+-----------+---------------+------------+----------------+
因此完全可以在定義為NOT NULL的列內(nèi)插入0或空字符串,實(shí)際是NOT NULL。
7. 模式匹配MySQL提供標(biāo)準(zhǔn)的SQL模式匹配,以及一種基于象Unix實(shí)用程序如vi、grep和sed的擴(kuò)展正則表達(dá)式模式匹配的格式。
SQL模式匹配允許你使用
“_”匹配任何單個(gè)字符,而
“%”匹配任意數(shù)目字符(包括零字符)。在 MySQL中,SQL的模式默認(rèn)是忽略大小寫(xiě)的。下面給出一些例子。注意使用SQL模式時(shí),不能使用=或!=;而應(yīng)使用LIKE或NOT LIKE比較操作符。
要想找出以
“b”開(kāi)頭的名字:
mysql> SELECT * FROM pet WHERE name LIKE ’b%’; +--------+--------+---------+------+------------+------------+| name | owner | species | sex | birth | death |+--------+--------+---------+------+------------+------------+| Buffy | Harold | dog | f | 1989-05-13 | NULL || Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 |+--------+--------+---------+------+------------+------------+
要想找出以
“fy”結(jié)尾的名字:
mysql> SELECT * FROM pet WHERE name LIKE ’%fy’; +--------+--------+---------+------+------------+-------+| name | owner | species | sex | birth | death |+--------+--------+---------+------+------------+-------+| Fluffy | Harold | cat | f | 1993-02-04 | NULL || Buffy | Harold | dog | f | 1989-05-13 | NULL |+--------+--------+---------+------+------------+-------+
要想找出包含
“w”的名字:
mysql> SELECT * FROM pet WHERE name LIKE ’%w%’; +----------+-------+---------+------+------------+------------+| name | owner | species | sex | birth | death |+----------+-------+---------+------+------------+------------+| Claws | Gwen | cat | m | 1994-03-17 | NULL || Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 || Whistler | Gwen | bird | NULL | 1997-12-09 | NULL |+----------+-------+---------+------+------------+------------+
要想找出正好包含5個(gè)字符的名字,使用
“_”模式字符:
mysql> SELECT * FROM pet WHERE name LIKE ’_____’; +-------+--------+---------+------+------------+-------+| name | owner | species | sex | birth | death |+-------+--------+---------+------+------------+-------+| Claws | Gwen | cat | m | 1994-03-17 | NULL || Buffy | Harold | dog | f | 1989-05-13 | NULL |+-------+--------+---------+------+------------+-------+
由MySQL提供的模式匹配的其它類(lèi)型是使用擴(kuò)展正則表達(dá)式。當(dāng)你對(duì)這類(lèi)模式進(jìn)行匹配測(cè)試時(shí),使用REGEXP和NOT REGEXP操作符(或RLIKE和NOT RLIKE,它們是同義詞)。
擴(kuò)展正則表達(dá)式的一些字符是:
· ‘.’匹配任何單個(gè)的字符。
· 字符類(lèi)
“[...]”匹配在方括號(hào)內(nèi)的任何字符。例如,
“[abc]”匹配
“a”、
“b”或
“c”。為了命名字符的范圍,使用一個(gè)“-”。
“[a-z]”匹配任何字母,而
“[0-9]”匹配任何數(shù)字。
·
“ * ”匹配零個(gè)或多個(gè)在它前面的字符。例如,
“x*”匹配任何數(shù)量的
“x”字符,
“[0-9]*”匹配任何數(shù)量的數(shù)字,而
“.*”匹配任何數(shù)量的任何字符。
如果REGEXP模式與被測(cè)試值的任何地方匹配,模式就匹配(這不同于LIKE模式匹配,只有與整個(gè)值匹配,模式才匹配)。為了定位一個(gè)模式以便它必須匹配被測(cè)試值的開(kāi)始或結(jié)尾,在模式開(kāi)始處使用“^”或
在模式的結(jié)尾用“$”。
為了說(shuō)明擴(kuò)展正則表達(dá)式如何工作,下面使用REGEXP重寫(xiě)上面所示的LIKE查詢(xún):
為了找出以
“b”開(kāi)頭的名字,使用
“^”匹配名字的開(kāi)始:
mysql> SELECT * FROM pet WHERE name REGEXP ’^b’; +--------+--------+---------+------+------------+------------+| name | owner | species | sex | birth | death |+--------+--------+---------+------+------------+------------+| Buffy | Harold | dog | f | 1989-05-13 | NULL || Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 |+--------+--------+---------+------+------------+------------+
如果你想強(qiáng)制使REGEXP比較區(qū)分大小寫(xiě),使用BINARY關(guān)鍵字使其中一個(gè)字符串變?yōu)槎M(jìn)制字符串。該查詢(xún)只匹配名稱(chēng)首字母的小寫(xiě)‘b’。
mysql> SELECT * FROM pet WHERE name REGEXP BINARY ’^b’;
為了找出以
“fy”結(jié)尾的名字,使用
“$”匹配名字的結(jié)尾:
mysql> SELECT * FROM pet WHERE name REGEXP ’fy$’; +--------+--------+---------+------+------------+-------+| name | owner | species | sex | birth | death |+--------+--------+---------+------+------------+-------+| Fluffy | Harold | cat | f | 1993-02-04 | NULL || Buffy | Harold | dog | f | 1989-05-13 | NULL |+--------+--------+---------+------+------------+-------+
為了找出包含一個(gè)
“w”的名字,使用以下查詢(xún):
mysql> SELECT * FROM pet WHERE name REGEXP ’w’; +----------+-------+---------+------+------------+------------+| name | owner | species | sex | birth | death |+----------+-------+---------+------+------------+------------+| Claws | Gwen | cat | m | 1994-03-17 | NULL || Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 || Whistler | Gwen | bird | NULL | 1997-12-09 | NULL |+----------+-------+---------+------+------------+------------+
既然如果一個(gè)正則表達(dá)式出現(xiàn)在值的任何地方,其模式匹配了,就不必在先前的查詢(xún)中在模式的兩側(cè)放置一個(gè)通配符以使得它匹配整個(gè)值,就像你使用了一個(gè)SQL模式那樣。
為了找出包含正好5個(gè)字符的名字,使用
“^”和
“$”匹配名字的開(kāi)始和結(jié)尾,和5個(gè)
“.”實(shí)例在兩者之間:
mysql> SELECT * FROM pet WHERE name REGEXP ’^.....$’; +-------+--------+---------+------+------------+-------+| name | owner | species | sex | birth | death |+-------+--------+---------+------+------------+-------+| Claws | Gwen | cat | m | 1994-03-17 | NULL || Buffy | Harold | dog | f | 1989-05-13 | NULL |+-------+--------+---------+------+------------+-------+
你也可以使用
“{n}”“重復(fù)n次”操作符重寫(xiě)前面的查詢(xún):
mysql> SELECT * FROM pet WHERE name REGEXP ’^.{5}$’; +-------+--------+---------+------+------------+-------+| name | owner | species | sex | birth | death |+-------+--------+---------+------+------------+-------+| Claws | Gwen | cat | m | 1994-03-17 | NULL || Buffy | Harold | dog | f | 1989-05-13 | NULL |+-------+--------+---------+------+------------+-------+8. 計(jì)數(shù)行
數(shù)據(jù)庫(kù)經(jīng)常用于回答這個(gè)問(wèn)題,“某個(gè)類(lèi)型的數(shù)據(jù)在表中出現(xiàn)的頻度?”例如,你可能想要知道你有多少寵物,或每位主人有多少寵物,或你可能想要對(duì)你的動(dòng)物進(jìn)行各種類(lèi)型的普查。計(jì)算你擁有動(dòng)物的總數(shù)目與“在pet表中有多少行?”是同樣的問(wèn)題,因?yàn)槊總€(gè)寵物有一個(gè)記錄。COUNT(*)函數(shù)計(jì)算行數(shù),所以計(jì)算動(dòng)物數(shù)目的查詢(xún)應(yīng)為:
mysql> SELECT COUNT(*) FROM pet; +----------+| COUNT(*) |+----------+|9 |+----------+
在前面,你檢索了擁有寵物的人的名字。如果你想要知道每個(gè)主人有多少寵物,你可以使用COUNT( )函數(shù):
mysql> SELECT owner, COUNT(*) FROM pet GROUP BY owner; +--------+----------+| owner | COUNT(*) |+--------+----------+| Benny |2 || Diane |2 || Gwen |3 || Harold |2 |+--------+----------+
注意,使用GROUP BY對(duì)每個(gè)owner的所有記錄分組,沒(méi)有它,你會(huì)得到錯(cuò)誤消息:
mysql> SELECT owner, COUNT(*) FROM pet; ERROR 1140 (42000): Mixing of GROUP columns (MIN(),MAX(),COUNT(),...)with no GROUP columns is illegal if there is no GROUP BY clause
COUNT( )和GROUP BY以各種方式分類(lèi)你的數(shù)據(jù)。下列例子顯示出進(jìn)行動(dòng)物普查操作的不同方式。
每種動(dòng)物的數(shù)量:
mysql> SELECT species, COUNT(*) FROM pet GROUP BY species; +---------+----------+| species | COUNT(*) |+---------+----------+| bird |2 || cat |2 || dog |3 || hamster |1 || snake |1 |+---------+----------+
每種性別的動(dòng)物數(shù)量:
mysql> SELECT sex, COUNT(*) FROM pet GROUP BY sex; +------+----------+| sex | COUNT(*) |+------+----------+| NULL |1 || f |4 || m |4 |+------+----------+
(在這個(gè)輸出中,NULL表示“未知性別”。)
按種類(lèi)和性別組合的動(dòng)物數(shù)量:
mysql> SELECT species, sex, COUNT(*) FROM pet GROUP BY species, sex; +---------+------+----------+| species | sex | COUNT(*) |+---------+------+----------+| bird | NULL |1 || bird | f |1 || cat | f |1 || cat | m |1 || dog | f |1 || dog | m |2 || hamster | f |1 || snake | m |1 |+---------+------+----------+
若使用COUNT( ),你不必檢索整個(gè)表。例如, 前面的查詢(xún),當(dāng)只對(duì)狗和貓進(jìn)行時(shí),應(yīng)為:
mysql> SELECT species, sex, COUNT(*) FROM pet -> WHERE species = ’dog’ OR species = ’cat’ -> GROUP BY species, sex; +---------+------+----------+| species | sex | COUNT(*) |+---------+------+----------+| cat | f |1 || cat | m |1 || dog | f |1 || dog | m |2 |+---------+------+----------+
或,如果你僅需要知道已知性別的按性別的動(dòng)物數(shù)目:
mysql> SELECT species, sex, COUNT(*) FROM pet -> WHERE sex IS NOT NULL -> GROUP BY species, sex; +---------+------+----------+| species | sex | COUNT(*) |+---------+------+----------+| bird | f |1 || cat | f |1 || cat | m |1 || dog | f |1 || dog | m |2 || hamster | f |1 || snake | m |1 |+---------+------+----------+9. 使用1個(gè)以上的表
pet表追蹤你有哪個(gè)寵物。如果你想要記錄其它相關(guān)信息,例如在他們一生中看獸醫(yī)或何時(shí)后代出生,你需要另外的表。這張表應(yīng)該像什么呢?需要:· 它需要包含寵物名字以便你知道每個(gè)事件屬于哪個(gè)動(dòng)物。
· 需要一個(gè)日期以便你知道事件是什么時(shí)候發(fā)生的。
· 需要一個(gè)描述事件的字段。
· 如果你想要對(duì)事件進(jìn)行分類(lèi),則需要一個(gè)事件類(lèi)型字段。
綜合上述因素,event表的CREATE TABLE語(yǔ)句應(yīng)為:
mysql> CREATE TABLE event (name VARCHAR(20), date DATE, -> type VARCHAR(15), remark VARCHAR(255));
對(duì)于pet表,最容易的方法是創(chuàng)建包含信息的用定位符分隔的文本文件來(lái)裝載初始記錄:
namedatetyperemarkFluffy1995-05-15litter4 kittens, 3 female, 1 maleBuffy1993-06-23litter5 puppies, 2 female, 3 maleBuffy1994-06-19litter3 puppies, 3 femaleChirpy1999-03-21vetneeded beak straightenedSlim1997-08-03vetbroken ribBowser1991-10-12kennelFang1991-10-12kennelFang1998-08-28birthdayGave him a new chew toyClaws1998-03-17birthdayGave him a new flea collarWhistler1998-12-09birthdayFirst birthday采用如下方式裝載記錄:
mysql> LOAD DATA LOCAL INFILE ’event.txt’ INTO TABLE event;
根據(jù)你從已經(jīng)運(yùn)行在pet表上的查詢(xún)中學(xué)到的,你應(yīng)該能執(zhí)行對(duì)event表中記錄的檢索;原理是一樣的。但是什么時(shí)候event表本身不能回答你可能問(wèn)的問(wèn)題呢?
當(dāng)他們有了一窩小動(dòng)物時(shí),假定你想要找出每只寵物的年齡。我們前面看到了如何通過(guò)兩個(gè)日期計(jì)算年齡。event表中有母親的生產(chǎn)日期,但是為了計(jì)算母親的年齡,你需要她的出生日期,存儲(chǔ)在pet表中。說(shuō)明查詢(xún)需要兩個(gè)表:
mysql> SELECT pet.name, -> (YEAR(date)-YEAR(birth)) - (RIGHT(date,5)<RIGHT(birth,5)) AS age, -> remark -> FROM pet, event -> WHERE pet.name = event.name AND event.type = ’litter’; +--------+------+-----------------------------+| name | age | remark |+--------+------+-----------------------------+| Fluffy | 2 | 4 kittens, 3 female, 1 male || Buffy | 4 | 5 puppies, 2 female, 3 male || Buffy | 5 | 3 puppies, 3 female |+--------+------+-----------------------------+
關(guān)于該查詢(xún)要注意的幾件事情:
FROM子句列出兩個(gè)表,因?yàn)椴樵?xún)需要從兩個(gè)表提取信息。當(dāng)從多個(gè)表組合(聯(lián)結(jié))信息時(shí),你需要指定一個(gè)表中的記錄怎樣能匹配其它表的記錄。這很簡(jiǎn)單,因?yàn)樗鼈兌加幸粋€(gè)name列。查詢(xún)使用WHERE子句基于name值來(lái)匹配2個(gè)表中的記錄。因?yàn)閚ame列出現(xiàn)在兩個(gè)表中,當(dāng)引用列時(shí),你一定要指定哪個(gè)表。把表名附在列名前即可以實(shí)現(xiàn)。你不必有2個(gè)不同的表來(lái)進(jìn)行聯(lián)結(jié)。如果你想要將一個(gè)表的記錄與同一個(gè)表的其它記錄進(jìn)行比較,可以將一個(gè)表聯(lián)結(jié)到自身。例如,為了在你的寵物之中繁殖配偶,你可以用pet聯(lián)結(jié)自身來(lái)進(jìn)行相似種類(lèi)的雄雌配對(duì):
mysql> SELECT p1.name, p1.sex, p2.name, p2.sex, p1.species -> FROM pet AS p1, pet AS p2 -> WHERE p1.species = p2.species AND p1.sex = ’f’ AND p2.sex = ’m’; +--------+------+--------+------+---------+| name | sex | name | sex | species |+--------+------+--------+------+---------+| Fluffy | f | Claws | m | cat || Buffy | f | Fang | m | dog || Buffy | f | Bowser | m | dog |+--------+------+--------+------+---------+
在這個(gè)查詢(xún)中,我們?yōu)楸砻付▌e名以便能引用列并且使得每一個(gè)列引用與哪個(gè)表實(shí)例相關(guān)聯(lián)更直觀。
相關(guān)文章:
1. 輕松解決SQL Server 2005中的常見(jiàn)問(wèn)題2. 快速解決mysql導(dǎo)出scv文件亂碼、躥行的問(wèn)題3. DB2 XML 全文搜索之為文本搜索做準(zhǔn)備4. MySQL 千萬(wàn)級(jí)數(shù)據(jù)量如何快速分頁(yè)5. 如何:創(chuàng)建和運(yùn)行 CLR SQL Server 存儲(chǔ)過(guò)程6. 用SQL SERVER記錄站點(diǎn)日志7. 數(shù)據(jù)庫(kù)人員手冊(cè)之ORACLE應(yīng)用源碼8. mssql鎖基礎(chǔ)教程9. MySQL基礎(chǔ)教程9 —— 函數(shù)之日期和時(shí)間函數(shù)10. centos 7安裝mysql5.5和安裝 mariadb使用的命令
