mysql 基本使用教程(源于网络)
本章通過演示如何使用mysql客戶程序創(chuàng)造和使用一個簡單的數(shù)據(jù)庫,提供一個MySQL的入門教程。mysql(有時稱為“終端監(jiān)視器”或只是“監(jiān)視”)是一個交互式程序,允許你連接一個MySQL服務(wù)器,運行查詢并察看結(jié)果。mysql可以用于批模式:你預(yù)先把查詢放在一個文件中,然后告訴mysql執(zhí)行文件的內(nèi)容。本章將介紹使用mysql的兩個方法。
要想查看由mysql提供的選擇項目表,可以用--help選項來調(diào)用:
shell> mysql --help本章假定mysql已經(jīng)被安裝在你的機(jī)器上,并且有一個MySQL服務(wù)器可以連接。否則,請聯(lián)絡(luò)MySQL管理員。(如果你是管理員,則需要查閱本手冊的其它章節(jié),例如第5章:數(shù)據(jù)庫管理。)
本章描述建立和使用一個數(shù)據(jù)庫的全過程。如果你僅僅對訪問一個已經(jīng)存在的數(shù)據(jù)庫感興趣,可以跳過描述怎樣創(chuàng)建數(shù)據(jù)庫及它所包含的表的章節(jié)。
由于本章是一個教程,省略了許多細(xì)節(jié)。關(guān)于這里所涉及的主題的詳細(xì)信息,請查閱本手冊的相關(guān)章節(jié)。
3.1.?連接與斷開服務(wù)器
為了連接服務(wù)器,當(dāng)調(diào)用mysql時,通常需要提供一個MySQL用戶名并且很可能需要一個 密碼。如果服務(wù)器運行在登錄服務(wù)器之外的其它機(jī)器上,還需要指定主機(jī)名。聯(lián)系管理員以找出進(jìn)行連接所使用的參數(shù)?(即,連接的主機(jī)、用戶名和使用的密碼)。知道正確的參數(shù)后,可以按照以下方式進(jìn)行連接:shell> mysql -h host -u user -p Enter password: ********host和user分別代表MySQL服務(wù)器運行的主機(jī)名和MySQL賬戶用戶名。設(shè)置時替換為正確的值。********?代表你的密碼;當(dāng)mysql顯示Enter password:提示時輸入它。
如果有效,你應(yīng)該看見mysql>提示符后的一些介紹信息:
shell> mysql -h host -u user -p Enter password: ******** Welcome to the MySQL monitor.? Commands end with ; or /g. Your MySQL connection id is 25338 to server version: 5.1.2-alpha-standard ? Type 'help;' or '/h' for help. Type '/c' to clear the buffer. ? mysql>mysql>?提示符告訴你mysql準(zhǔn)備為你輸入命令。
一些MySQL安裝允許用戶以匿名(未命名)用戶連接到本地主機(jī)上運行的服務(wù)器。如果你的機(jī)器是這種情況,你應(yīng)該能不帶任何選項地調(diào)用mysql與該服務(wù)器連接:
shell> mysql成功地連接后,可以在mysql>提示下輸入QUIT?(或/q)隨時退出:
mysql> QUIT Bye在Unix中,也可以按control-D鍵斷開服務(wù)器。
在下列章節(jié)的大多數(shù)例子都假設(shè)你連接到了服務(wù)器。由mysql>提示指明。
3.2.?輸入查詢
確保你連接上了服務(wù)器,如在先前的章節(jié)討論的。連接上服務(wù)器并布代表選擇了任何數(shù)據(jù)庫,但這樣就可以了。知道關(guān)于如何查詢的基本知識,比馬上跳至創(chuàng)建表、給他們裝載數(shù)據(jù)并且從他們檢索數(shù)據(jù)更重要。本節(jié)描述輸入命令的基本原則,使用幾個查詢,你能嘗試了解mysql是如何工作的。
這是一個簡單的命令,要求服務(wù)器告訴它的版本號和當(dāng)前日期。在mysql>提示輸入如下命令并按回車鍵:
mysql> SELECT VERSION(), CURRENT_DATE; +-----------------+--------------+ | VERSION()?????? | CURRENT_DATE | +-----------------+--------------+ | 5.1.2-alpha-log | 2005-10-11?? | +-----------------+--------------+ 1 row in set (0.01 sec) mysql>這詢問說明mysql的幾個方面:
·?????????一個命令通常由SQL語句組成,隨后跟著一個分號。(有一些例外不需要分號。早先提到的QUIT是一個例子。后面我們將看到其它的例子。)
·?????????當(dāng)發(fā)出一個命令時,mysql將它發(fā)送給服務(wù)器并顯示執(zhí)行結(jié)果,然后顯示另一個mysql>顯示它準(zhǔn)備好接受其它命令。
·?????????mysql用表格(行和列)方式顯示查詢輸出。第一行包含列的標(biāo)簽,隨后的行是查詢結(jié)果。通常,列標(biāo)簽是你取自數(shù)據(jù)庫表的列的名字。如果你正在檢索一個表達(dá)式而非表列的值(如剛才的例子),mysql用表達(dá)式本身標(biāo)記列。
·?????????mysql顯示返回了多少行,以及查詢花了多長時間,它給你提供服務(wù)器性能的一個大致概念。因為他們表示時鐘時間(不是?CPU?或機(jī)器時間),并且因為他們受到諸如服務(wù)器負(fù)載和網(wǎng)絡(luò)延時的影響,因此這些值是不精確的。(為了簡潔,在本章其它例子中不再顯示“集合中的行”。)
能夠以大小寫輸入關(guān)鍵詞。下列查詢是等價的:
mysql> SELECT VERSION(), CURRENT_DATE; mysql> select version(), current_date; mysql> SeLeCt vErSiOn(), current_DATE;這是另外一個查詢,它說明你能將mysql用作一個簡單的計算器:
mysql> SELECT SIN(PI()/4), (4+1)*5; +------------------+---------+ | SIN(PI()/4)????? | (4+1)*5 | +------------------+---------+ | 0.70710678118655 |????? 25 | +------------------+---------+ 1 row in set (0.02 sec)至此顯示的命令是相當(dāng)短的單行語句。你可以在一行上輸入多條語句,只需要以一個分號間隔開各語句:
mysql> SELECT VERSION(); SELECT NOW(); +-----------------+ | VERSION()?????? | +-----------------+ | 5.1.2-alpha-log | +-----------------+ 1 row in set (0.00 sec) ? +---------------------+ | NOW()?????????????? | +---------------------+ | 2005-10-11 15:15:00 | +---------------------+ 1 row in set (0.00 sec)不必全在一個行內(nèi)給出一個命令,較長命令可以輸入到多個行中。mysql通過尋找終止分號而不是輸入行的結(jié)束來決定語句在哪兒結(jié)束。(換句話說,mysql接受自由格式的輸入:它收集輸入行但直到看見分號才執(zhí)行。)
這里是一個簡單的多行語句的例子:
mysql> SELECT ??? -> USER() ??? -> , ??? -> CURRENT_DATE; +---------------+--------------+ | USER()??????? | CURRENT_DATE | +---------------+--------------+ | jon@localhost | 2005-10-11?? | +---------------+--------------+在這個例子中,在輸入多行查詢的第一行后,要注意提示符如何從mysql>變?yōu)?>,這正是mysql如何指出它沒見到完整的語句并且正在等待剩余的部分。提示符是你的朋友,因為它提供有價值的反饋,如果使用該反饋,將總是知道mysql正在等待什么。
如果你決定不想執(zhí)行正在輸入過程中的一個命令,輸入/c取消它:
mysql> SELECT ??? -> USER() ??? -> /c mysql>這里也要注意提示符,在你輸入/c以后,它切換回到mysql>,提供反饋以表明mysql準(zhǔn)備接受一個新命令。
下表顯示出可以看見的各個提示符并簡述它們所表示的mysql的狀態(tài):
| 提示符 | 含義 |
| mysql> | 準(zhǔn)備好接受新命令。 |
| -> | 等待多行命令的下一行。 |
| '> | 等待下一行,等待以單引號(“'”)開始的字符串的結(jié)束。 |
| "> | 等待下一行,等待以雙引號(“"”)開始的字符串的結(jié)束。 |
| `> | 等待下一行,等待以反斜點(‘`’)開始的識別符的結(jié)束。 |
| /*> | 等待下一行,等待以/*開始的注釋的結(jié)束。 |
當(dāng)你打算在一個單行上發(fā)出一個命令時,通常會“偶然”出現(xiàn)多行語句,但是沒有終止分號。在這種情況中,mysql等待進(jìn)一步輸入:
mysql> SELECT USER() ??? ->如果出現(xiàn)這種情況(你認(rèn)為輸完了語句,但是只有一個->提示符響應(yīng)),很可能mysql正在等待分號。如果你沒有注意到提示符的提示,在意識到你需要做什么之前,你可能會呆坐一會兒。輸入一個分號完成語句,mysql將執(zhí)行:
mysql> SELECT USER() ??? -> ; +---------------+ | USER()??????? | +---------------+ | jon@localhost | +---------------+在字符串收集期間將出現(xiàn)?'>?和?">?提示符(提示MySQL正等待字符串的結(jié)束)。在MySQL中,可以寫由‘'’或‘"’字符括起來的字符串?(例如,'hello'或"goodbye"),并且mysql允許輸入跨越多行的字符串。當(dāng)看到一個?'>?或?">?提示符時,這意味著已經(jīng)輸入了包含以‘'’或‘"’括號字符開始的字符串的一行,但是還沒有輸入終止字符串的匹配引號。這顯示你粗心地省掉了一個引號字符。例如:
mysql> SELECT * FROM my_table WHERE name = 'Smith AND age < 30; ??? '>如果你輸入SELECT語句,然后按Enter(回車)鍵并等待結(jié)果,什么都沒有出現(xiàn)。不要驚訝,“為什么該查詢這么長呢?”,注意">提示符提供的線索。它告訴你mysql期望見到一個未終止字符串的余下部分。(你看見語句中的錯誤嗎?字符串"Smith丟掉了第二個引號。)
走到這一步,你該做什么?最簡單的是取消命令。然而,在這種情況下,你不能只是輸入/c,因為mysql作為它正在收集的字符串的一部分來解釋它!相反,應(yīng)輸入關(guān)閉的引號字符(這樣mysql知道你完成了字符串),然后輸入/c:
mysql> SELECT * FROM my_table WHERE name = 'Smith AND age < 30; ??? '> '/c mysql>提示符回到mysql>,顯示mysql準(zhǔn)備好接受一個新命令了。
`>?提示符類似于?'>?和">?提示符,但表示你已經(jīng)開始但沒有結(jié)束以`>?開始的識別符。
知道'>和">提示符的含義很重要,因為如果你錯誤地輸入一個未終止的字符串,任何后面輸入的行將要被mysql忽略--包括包含QUIT的行!這可能令人相當(dāng)困惑,特別是如果取消當(dāng)前命令前還不知道你需要提供終止引號。
3.3.?創(chuàng)建并使用數(shù)據(jù)庫
3.3.1. 創(chuàng)建并選擇數(shù)據(jù)庫3.3.2. 創(chuàng)建表3.3.3. 將數(shù)據(jù)裝入表中3.3.4. 從表檢索信息知道怎樣輸入命令,便可以訪問數(shù)據(jù)庫了。
假定在你的家(你的“動物園”)中有很多寵物,并且你想跟蹤關(guān)于它們各種類型的信息。你可以通過創(chuàng)建表來保存你的數(shù)據(jù)并根據(jù)所需要的信息裝載他們,然后你可以從表中檢索數(shù)據(jù)來回答關(guān)于動物不同種類的問題。本節(jié)顯示如何做到所有這些事情:
·?????????創(chuàng)建數(shù)據(jù)庫
·?????????創(chuàng)建數(shù)據(jù)庫表
·?????????裝載數(shù)據(jù)到數(shù)據(jù)庫表
·?????????以各種方法從表中檢索數(shù)據(jù)
·?????????使用多個表
動物園數(shù)據(jù)庫很簡單(特意的),但是不難把它想象成可能用到類似數(shù)據(jù)庫的真實世界情況。例如,農(nóng)夫可以使用這樣的一個數(shù)據(jù)庫來追蹤家畜,或者獸醫(yī)可以用它跟蹤病畜記錄。從MySQL網(wǎng)址上可以獲得后面章節(jié)中將用到的含有部分查詢和樣例數(shù)據(jù)的動物園分發(fā)。有tar壓縮格式?(http://downloads.mysql.com/docs/menagerie-db.tar.gz)和Zip壓縮格式?(http://downloads.mysql.com/docs/menagerie-db.zip)。
使用SHOW語句找出服務(wù)器上當(dāng)前存在什么數(shù)據(jù)庫:
mysql> SHOW DATABASES; +----------+ | Database | +----------+ | mysql??? | | test???? | | tmp????? | +----------+可能你的機(jī)器上的數(shù)據(jù)庫列表是不同的,但是很可能有mysql和test數(shù)據(jù)庫。mysql是必需的,因為它描述用戶訪問權(quán)限,test數(shù)據(jù)庫經(jīng)常作為用戶試身手的工作區(qū)。
請注意如果沒有SHOW DATABASES權(quán)限,則不能看見所有數(shù)據(jù)庫。參見13.5.1.3節(jié),“GRANT和REVOKE語法”。
如果test數(shù)據(jù)庫存在,嘗試訪問它:
mysql> USE test Database changed注意,USE,類似QUIT,不需要一個分號。(如果你喜歡,你可以用一個分號終止這樣的語句;這無礙)USE語句在使用上也有另外一個特殊的地方:它必須在一個單行上給出。
你可列在后面的例子中使用test數(shù)據(jù)庫(如果你能訪問它),但是你在該數(shù)據(jù)庫創(chuàng)建的任何東西可以被訪問它的其它人刪除,因此,你應(yīng)該詢問MySQL管理員許可你使用自己的一個數(shù)據(jù)庫。假定你想要調(diào)用你的menagerie,管理員需要執(zhí)行這樣一條命令:
mysql> GRANT ALL ON menagerie.* TO 'your_mysql_name'@'your_client_host';這里your_mysql_name是分配給你的MySQL用戶名,your_client_host是所連接的服務(wù)器所在的主機(jī)。
3.3.1.?創(chuàng)建并選擇數(shù)據(jù)庫
如果管理員在設(shè)置權(quán)限時為你創(chuàng)建了數(shù)據(jù)庫,你可以開始使用它。否則,你需要自己創(chuàng)建數(shù)據(jù)庫:mysql> CREATE DATABASE menagerie;在Unix下,數(shù)據(jù)庫名稱是區(qū)分大小寫的(不像SQL關(guān)鍵字),因此你必須總是以menagerie訪問數(shù)據(jù)庫,而不能用Menagerie、MENAGERIE或其它一些變量。對表名也是這樣的。(在Windows下,該限制不適用,盡管你必須在一個給定的查詢中使用同樣的大小寫來引用數(shù)據(jù)庫和表。但是,由于多種原因,作為最好的慣例,一定要使用與數(shù)據(jù)庫創(chuàng)建時的同樣的大小寫。)
創(chuàng)建數(shù)據(jù)庫并不表示選定并使用它,你必須明確地操作。為了使menagerie成為當(dāng)前的數(shù)據(jù)庫,使用這個命令:
mysql> USE menagerie Database changed數(shù)據(jù)庫只需要創(chuàng)建一次,但是必須在每次啟動mysql會話時在使用前先選擇它。你可以根據(jù)上面的例子執(zhí)行一個USE語句來實現(xiàn)。還可以在調(diào)用mysql時,通過命令行選擇數(shù)據(jù)庫,只需要在提供連接參數(shù)之后指定數(shù)據(jù)庫名稱。例如:
shell> mysql -h host -u user -p menagerie Enter password: ********注意,剛才顯示的命令行中的menagerie不是你的 密碼。如果你想要在命令行上在-p選項后提供 密碼,則不能插入空格(例如,如-pmypassword,不是-p mypassword)。但是,不建議在命令行輸入密碼,因為這樣會暴露 密碼,能被在機(jī)器上登錄的其它用戶窺探到。
3.3.2.?創(chuàng)建表
創(chuàng)建數(shù)據(jù)庫是很容易的部分,但是在這時它是空的,正如SHOW TABLES將告訴你的:
mysql> SHOW TABLES; Empty set (0.00 sec)較難的部分是決定你的數(shù)據(jù)庫結(jié)構(gòu)應(yīng)該是什么:你需要什么數(shù)據(jù)庫表,各數(shù)據(jù)庫表中有什么樣的列。
你將需要一個包含你每個寵物的記錄的表。它可稱為pet表,并且它應(yīng)該包含,最少,每個動物的名字。因為名字本身不是很有趣,表應(yīng)該包含另外的信息。例如,如果在你豢養(yǎng)寵物的家庭有超過一個人,你可能想要列出每個動物的主人。你可能也想要記錄例如種類和性別的一些基本的描述信息。
年齡呢?那可能有趣,但是存儲到一個數(shù)據(jù)庫中不是一件好事情。年齡隨著時間流逝而變化,這意味著你將要不斷地更新你的記錄。相反,?存儲一個固定值例如生日比較好,那么,無論何時你需要年齡,可以以當(dāng)前日期和出生日期之間的差來計算它。MySQL提供了日期運算函數(shù),因此這并不困難。存儲出生日期而非年齡還有其它優(yōu)點:
·?????????你可以使用數(shù)據(jù)庫完成這樣的任務(wù),例如生成即將到來的寵物生日的提示。(如果你認(rèn)為這類查詢有點蠢,注意,這與從商務(wù)數(shù)據(jù)庫來識別出不久要發(fā)給生日祝賀的客戶是同一個問題,因為計算機(jī)幫助私人聯(lián)絡(luò)。)
·?????????你可以相對于日期而不止是當(dāng)前日期來計算年齡。例如,如果你在數(shù)據(jù)庫存儲死亡日期,你能很容易地計算出一只寵物死時有多大。
你可能想到pet表中其它有用的其它類型信息,但是到目前為止這些已經(jīng)足夠了:名字、主人、種類,性別、出生和死亡日期。
使用一個CREATE TABLE語句指定你的數(shù)據(jù)庫表的布局:
mysql> CREATE TABLE pet (name VARCHAR(20), owner VARCHAR(20), ??? -> species VARCHAR(20), sex CHAR(1), birth DATE, death DATE);VARCHAR適合于name、owner和species列,因為列值是變長的。這些列的長度不必都相同,而且不必是20。你可以挑選從1到65535的任何長度,從中選擇一個最合理的值。(如果選擇得不合適,后來證明你需要一個更長的字段,MySQL提供一個ALTER TABLE語句。)
可以用多種類型的值來表示動物記錄中的性別,例如,"m"和"f",或"male"和"female"。使用單字符"m"和"f"是最簡單的方法。
很顯然,birth和death列應(yīng)選用DATE數(shù)據(jù)類。
創(chuàng)建了數(shù)據(jù)庫表后,SHOW TABLES應(yīng)該產(chǎn)生一些輸出:
mysql> SHOW TABLES; +---------------------+ | Tables in menagerie | +---------------------+ | pet???????????????? | +---------------------+為了驗證你的表是按你期望的方式創(chuàng)建,使用一個DESCRIBE語句:
mysql> DESCRIBE pet; +---------+-------------+------+-----+---------+-------+ | Field?? | Type??????? | Null | Key | Default | Extra | +---------+-------------+------+-----+---------+-------+ | name??? | varchar(20) | YES? |???? | NULL??? |?????? | | owner?? | varchar(20) | YES? |???? | NULL??? |?????? | | species | varchar(20) | YES? |???? | NULL??? |?????? | | sex???? | char(1)???? | YES? |???? | NULL??? |?????? | | birth?? | date??????? | YES? |? ???| NULL??? |?????? | | death?? | date??????? | YES? |???? | NULL??? |?????? | +---------+-------------+------+-----+---------+-------+你可以隨時使用DESCRIBE,例如,如果你忘記表中的列的名稱或類型時。
3.3.3.?將數(shù)據(jù)裝入表中
創(chuàng)建表后,需要填入內(nèi)容。通過LOAD DATA和INSERT語句可以完成該任務(wù)。
假定你的寵物紀(jì)錄描述如下。(假定在MySQL中期望的日期格式是YYYY-MM-DD;這可能與你習(xí)慣的不同。)
| name | owner | species | sex | birth | death |
| Fluffy | Harold | cat | f | 1993-02-04 | ? |
| Claws | Gwen | cat | m | 1994-03-17 | ? |
| Buffy | Harold | dog | f | 1989-05-13 | ? |
| Fang | Benny | dog | m | 1990-08-27 | ? |
| Bowser | Diane | dog | m | 1979-08-31 | 1995-07-29 |
| Chirpy | Gwen | bird | f | 1998-09-11 | ? |
| Whistler | Gwen | bird | ? | 1997-12-09 | ? |
| Slim | Benny | snake | m | 1996-04-29 | ? |
因為你是從一個空表開始的,填充它的一個簡易方法是創(chuàng)建一個文本文件,每個動物各一行,然后用一個語句將文件的內(nèi)容裝載到表中。
你可以創(chuàng)建一個文本文件“pet.txt”,每行包含一個記錄,用定位符(tab)把值分開,并且以CREATE TABLE語句中列出的列次序給出。對于丟失的值(例如未知的性別,或仍然活著的動物的死亡日期),你可以使用NULL值。為了在你的文本文件中表示這些內(nèi)容,使用/N(反斜線,字母N)。例如,Whistler鳥的記錄應(yīng)為(這里值之間的空白是一個定位符):
| name | owner | species | sex | birth | death |
| Whistler | Gwen | bird | /N | 1997-12-09 | /N |
要想將文本文件“pet.txt”裝載到pet表中,使用這個命令:
mysql> LOAD DATA LOCAL INFILE '/path/pet.txt' INTO TABLE pet;請注意如果用Windows中的編輯器(使用/r/n做為行的結(jié)束符)創(chuàng)建文件,應(yīng)使用:
mysql> LOAD DATA LOCAL INFILE '/path/pet.txt' INTO TABLE pet ??? -> LINES TERMINATED BY '/r/n';(在運行OS X的Apple機(jī)上,應(yīng)使用行結(jié)束符'/r'。)
如果你愿意,你能明確地在LOAD DATA語句中指出列值的分隔符和行尾標(biāo)記,但是默認(rèn)標(biāo)記是定位符和換行符。這對讀入文件“pet.txt”的語句已經(jīng)足夠。
如果該語句失敗,可能是你安裝的MySQL不與使用默認(rèn)值的本地文件兼容。關(guān)于如何更改請參見5.6.4節(jié),“LOAD DATA LOCAL安全問題”。
如果想要一次增加一個新記錄,可以使用INSERT語句。最簡單的形式是,提供每一列的值,其順序與CREATE TABLE語句中列的順序相同。假定Diane把一只新倉鼠命名為Puffball,你可以使用下面的INSERT語句添加一條新記錄:
mysql> INSERT INTO pet ??? -> VALUES ('Puffball','Diane','hamster','f','1999-03-30',NULL);注意,這里字符串和日期值均為引號擴(kuò)起來的字符串。另外,可以直接用INSERT語句插入NULL代表不存在的值。不能使用LOAD DATA中所示的的/N。
從這個例子,你應(yīng)該能看到涉及很多的鍵入用多個INSERT語句而非單個LOAD DATA語句裝載你的初始記錄。
3.3.4.?從表檢索信息
3.3.4.1. 選擇所有數(shù)據(jù)3.3.4.2. 選擇特殊行3.3.4.3. 選擇特殊列3.3.4.4. 分類行3.3.4.5. 日期計算3.3.4.6. NULL值操作3.3.4.7. 模式匹配3.3.4.8. 計數(shù)行3.3.4.9. 使用1個以上的表? SELECT語句用來從數(shù)據(jù)表中檢索信息。語句的一般格式是:SELECT what_to_select FROM which_table WHERE conditions_to_satisfy;
what_to_select指出你想要看到的內(nèi)容,可以是列的一個表,或*表示“所有的列”。which_table指出你想要從其檢索數(shù)據(jù)的表。WHERE子句是可選項,如果選擇該項,conditions_to_satisfy指定行必須滿足的檢索條件。
3.3.4.1.?選擇所有數(shù)據(jù)
SELECT最簡單的形式是從一個表中檢索所有記錄: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?????? | +----------+--------+---------+------+------------+------------+如果你想要瀏覽整個表,可以使用這種形式的SELECT,例如,剛剛裝載了初始數(shù)據(jù)集以后。也有可能你想到Bowser的生日看起來不很對。查閱你原來的家譜,你發(fā)現(xiàn)正確的出生年是1989,而不是1979。
至少有兩種修正方法:
·?????????編輯文件“pet.txt”改正錯誤,然后使用DELETE和LOAD DATA清空并重新裝載表:
·??????????????? mysql> DELETE FROM pet; ·??????????????? mysql> LOAD DATA LOCAL INFILE 'pet.txt' INTO TABLE pet;然而,?如果這樣操做,必須重新輸入Puffball記錄。
·?????????用一個UPDATE語句僅修正錯誤記錄:
·??????????????? mysql> UPDATE pet SET birth = '1989-08-31' WHERE name = 'Bowser';UPDATE只更改有問題的記錄,不需要重新裝載數(shù)據(jù)庫表。
3.3.4.2.?選擇特殊行
如上所示,檢索整個表是容易的。只需要從SELECT語句中刪掉WHERE子句。但是一般你不想看到整個表,特別地當(dāng)表變得很大時。相反,你通常對回答一個具體的問題更感興趣,在這種情況下在你想要的信息上進(jìn)行一些限制。讓我們看一些他們回答的有關(guān)你寵物的問題的選擇查詢。可以從表中只選擇特定的行。例如,如果你想要驗證你對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 | +--------+-------+---------+------+------------+------------+輸出證實正確的年份記錄為1989,而不是1979。
字符串比較時通常對大小些不敏感,因此你可以將名字指定為"bowser"、"BOWSER"等,查詢結(jié)果相同。
你可以在任何列上指定條件,不只僅僅是name。例如,如果你想要知道哪個動物在1998以后出生的,測試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? | +-------+--------+---------+------+------------+-------+上面的查詢使用AND邏輯操作符,也有一個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ìn)行分組是一個好主意:
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.3.4.3.?選擇特殊列
如果你不想看到表中的所有行,就命名你感興趣的列,用逗號分開。例如,如果你想要知道你的動物什么時候出生的,選擇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 | +----------+------------+找出誰擁有寵物,使用這個查詢:
mysql> SELECT owner FROM pet; +--------+ | owner? | +--------+ | Harold | | Gwen?? | | Harold | | Benny? | | Diane? | | Gwen?? | | Gwen?? | | Benny? | | Diane? | +--------+請注意該查詢只是簡單地檢索每個記錄的owner列,并且他們中的一些出現(xiàn)多次。為了使輸出減到最少,增加關(guān)鍵字DISTINCT檢索出每個唯一的輸出記錄:
mysql> SELECT DISTINCT owner FROM pet; +--------+ | owner? | +--------+ | Benny? | | Diane? | | Gwen?? | | Harold | +--------+可以使用一個WHERE子句結(jié)合行選擇與列選擇。例如,要想查詢狗和貓的出生日期,使用這個查詢:
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 | +--------+---------+------------+3.3.4.4.?分類行
你可能已經(jīng)注意到前面的例子中結(jié)果行沒有以特定的順序顯示。然而,當(dāng)行按某種方式排序時,檢查查詢輸出通常更容易。為了排序結(jié)果,使用ORDER BY子句。這里是動物生日,按日期排序:
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 | +----------+------------+在字符類型列上,與所有其他比較操作類似,分類功能正常情況下是以區(qū)分大小寫的方式執(zhí)行的。這意味著,對于等同但大小寫不同的列,并未定義其順序。對于某一列,可以使用BINARY強(qiáng)制執(zhí)行區(qū)分大小寫的分類功能,如: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 | +----------+------------+可以對多個列進(jìn)行排序,并且可以按不同的方向?qū)Σ煌牧羞M(jìn)行排序。例如,按升序?qū)游锏姆N類進(jìn)行排序,然后按降序根據(jù)生日對各動物種類進(jì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列的排序順序。
3.3.4.5.?日期計算
MySQL提供了幾個函數(shù),可以用來計算日期,例如,計算年齡或提取日期部分。
要想確定每個寵物有多大,可以計算當(dāng)前日期的年和出生日期之間的差。如果當(dāng)前日期的日歷年比出生日期早,則減去一年。以下查詢顯示了每個寵物的出生日期、當(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個字符。比較MM-DD值的表達(dá)式部分的值一般為1或0,如果CURDATE()的年比birth的年早,則年份應(yīng)減去1。整個表達(dá)式有些難懂,使用alias?(age)來使輸出的列標(biāo)記更有意義。
盡管查詢可行,如果以某個順序排列行,則能更容易地瀏覽結(jié)果。添加ORDER BY name子句按照名字對輸出進(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排序輸出,只要再使用一個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 | +----------+------------+------------+------+可以使用一個類似的查詢來確定已經(jīng)死亡動物的死亡年齡。你通過檢查death值是否是NULL來確定是哪些動物,然后,對于那些非NULL值的動物,需要計算出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 | +--------+------------+------------+------+查詢使用death IS NOT NULL而非death != NULL,因為NULL是特殊的值,不能使用普通比較符來比較,以后會給出解釋。參見3.3.4.6節(jié),“NULL值操作”。
如果你想要知道哪個動物下個月過生日,怎么辦?對于這類計算,年和天是無關(guān)的,你只需要提取birth列的月份部分。MySQL提供幾個日期部分的提取函數(shù),例如YEAR( )、MONTH( )和DAYOFMONTH( )。在這里MONTH()是適合的函數(shù)。為了看它怎樣工作,運行一個簡單的查詢,顯示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 | +----------+------------+--------------+找出下個月生日的動物也是容易的。假定當(dāng)前月是4月,那么月值是4,你可以找在5月出生的動物?(5月),方法是:
mysql> SELECT name, birth FROM pet WHERE MONTH(birth) = 5; +-------+------------+ | name? | birth????? | +-------+------------+ | Buffy | 1989-05-13 | +-------+------------+如果當(dāng)前月份是12月,就有點復(fù)雜了。你不能只把1加到月份數(shù)(12)上并尋找在13月出生的動物,因為沒有這樣的月份。相反,你應(yīng)尋找在1月出生的動物(1月)?。
你甚至可以編寫查詢,不管當(dāng)前月份是什么它都能工作。采用這種方法不必在查詢中使用一個特定的月份,DATE_ADD( )允許在一個給定的日期上加上時間間隔。如果在NOW( )值上加上一個月,然后用MONTH()提取月份,結(jié)果產(chǎn)生生日所在月份:
mysql> SELECT name, birth FROM pet ??? -> WHERE MONTH(birth) = MONTH(DATE_ADD(CURDATE(),INTERVAL 1 MONTH));完成該任務(wù)的另一個方法是加1以得出當(dāng)前月份的下一個月(在使用取模函數(shù)(MOD)后,如果月份當(dāng)前值是12,則“回滾”到值0):
mysql> SELECT name, birth FROM pet ??? -> WHERE MONTH(birth) = MOD(MONTH(CURDATE()), 12) + 1;注意,MONTH返回在1和12之間的一個數(shù)字,且MOD(something,12)返回在0和11之間的一個數(shù)字,因此必須在MOD( )以后加1,否則我們將從11月( 11 )跳到1月(1)。
3.3.4.6.?NULL值操作
NULL值可能令人感到奇怪直到你習(xí)慣它。概念上,NULL意味著“沒有值”或“未知值”,且它被看作與眾不同的值。為了測試NULL,你不能使用算術(shù)比較 操作符例如=、<或!=。為了說明它,試試下列查詢:
mysql> SELECT 1 = NULL, 1 <> NULL, 1 < NULL, 1 > NULL; +----------+-----------+----------+----------+ | 1 = NULL | 1 <> NULL | 1 < NULL | 1 > NULL | +----------+-----------+----------+----------+ |???? NULL |????? NULL |???? NULL |???? NULL | +----------+-----------+----------+----------+很顯然你不能通過這些比較得到有意義的結(jié)果。相反使用IS NULL和IS NOT NULL操作符:
mysql> SELECT 1 IS NULL, 1 IS NOT NULL; +-----------+---------------+ | 1 IS NULL | 1 IS NOT NULL | +-----------+---------------+ |???????? 0 |???????????? 1 | +-----------+---------------+請注意在MySQL中,0或?NULL意味著假而其它值意味著真。布爾運算的默認(rèn)真值是1。
對NULL的特殊處理即是在前面的章節(jié)中,為了決定哪個動物不再是活著的,使用death IS NOT NULL而不使用death != NULL的原因。
在GROUP BY中,兩個NULL值視為相同。
執(zhí)行ORDER BY時,如果運行?ORDER BY ... ASC,則NULL值出現(xiàn)在最前面,若運行ORDER BY ... DESC,則NULL值出現(xiàn)在最后面。
NULL操作的常見錯誤是不能在定義為NOT NULL的列內(nèi)插入0或空字符串,但事實并非如此。在NULL表示"沒有數(shù)值"的地方有數(shù)值。使用IS?[NOT]?NULL則可以很容易地進(jìn)行測試,如下所示:
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或空字符串,實際是NOT NULL。參見A.5.3節(jié),“與NULL值有關(guān)的問題”。
3.3.4.7.?模式匹配
MySQL提供標(biāo)準(zhǔn)的SQL模式匹配,以及一種基于象Unix實用程序如vi、grep和sed的擴(kuò)展正則表達(dá)式模式匹配的格式。
SQL模式匹配允許你使用“_”匹配任何單個字符,而“%”匹配任意數(shù)目字符(包括零字符)。在MySQL中,SQL的模式默認(rèn)是忽略大小寫的。下面給出一些例子。注意使用SQL模式時,不能使用=或!=;而應(yīng)使用LIKE或NOT LIKE比較操作符。
要想找出以“b”開頭的名字:
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個字符的名字,使用“_”模式字符:
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提供的模式匹配的其它類型是使用擴(kuò)展正則表達(dá)式。當(dāng)你對這類模式進(jìn)行匹配測試時,使用REGEXP和NOT REGEXP操作符(或RLIKE和NOT RLIKE,它們是同義詞)。
擴(kuò)展正則表達(dá)式的一些字符是:
·?????????‘.’匹配任何單個的字符。
·?????????字符類“[...]”匹配在方括號內(nèi)的任何字符。例如,“[abc]”匹配“a”、“b”或“c”。為了命名字符的范圍,使用一個“-”。“[a-z]”匹配任何字母,而“[0-9]”匹配任何數(shù)字。
·?????????“?*?”匹配零個或多個在它前面的字符。例如,“x*”匹配任何數(shù)量的“x”字符,“[0-9]*”匹配任何數(shù)量的數(shù)字,而“.*”匹配任何數(shù)量的任何字符。
- 如果REGEXP模式與被測試值的任何地方匹配,模式就匹配(這不同于LIKE模式匹配,只有與整個值匹配,模式才匹配)。
- 為了定位一個模式以便它必須匹配被測試值的開始或結(jié)尾,在模式開始處使用“^”或在模式的結(jié)尾用“$”。
為了說明擴(kuò)展正則表達(dá)式如何工作,下面使用REGEXP重寫上面所示的LIKE查詢:
為了找出以“b”開頭的名字,使用“^”匹配名字的開始:
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ū)分大小寫,使用BINARY關(guān)鍵字使其中一個字符串變?yōu)槎M(jìn)制字符串。該查詢只匹配名稱首字母的小寫‘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? | +--------+--------+---------+------+------------+-------+為了找出包含一個“w”的名字,使用以下查詢:
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?????? | +----------+-------+---------+------+------------+------------+既然如果一個正則表達(dá)式出現(xiàn)在值的任何地方,其模式匹配了,就不必在先前的查詢中在模式的兩側(cè)放置一個通配符以使得它匹配整個值,就像你使用了一個SQL模式那樣。
為了找出包含正好5個字符的名字,使用“^”和“$”匹配名字的開始和結(jié)尾,和5個“.”實例在兩者之間:
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次”操作符重寫前面的查詢:
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? | +-------+--------+---------+------+------------+-------+附錄G:MySQL正則表達(dá)式?提供了關(guān)于正則表達(dá)式的句法的詳細(xì)信息。
3.3.4.8.?計數(shù)行
數(shù)據(jù)庫經(jīng)常用于回答這個問題,“某個類型的數(shù)據(jù)在表中出現(xiàn)的頻度?”例如,你可能想要知道你有多少寵物,或每位主人有多少寵物,或你可能想要對你的動物進(jìn)行各種類型的普查。計算你擁有動物的總數(shù)目與“在pet表中有多少行?”是同樣的問題,因為每個寵物有一個記錄。COUNT(*)函數(shù)計算行數(shù),所以計算動物數(shù)目的查詢應(yīng)為:
mysql> SELECT COUNT(*) FROM pet; +----------+ | COUNT(*) | +----------+ |??????? 9 | +----------+在前面,你檢索了擁有寵物的人的名字。如果你想要知道每個主人有多少寵物,你可以使用COUNT( )函數(shù):
mysql> SELECT owner, COUNT(*) FROM pet GROUP BY owner; +--------+----------+ | owner? | COUNT(*) | +--------+----------+ | Benny? |??????? 2 | | Diane? |??????? 2 | | Gwen?? |??????? 3 | | Harold |??????? 2 | +--------+----------+注意,使用GROUP BY對每個owner的所有記錄分組,沒有它,你會得到錯誤消息:
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 clauseCOUNT( )和GROUP BY以各種方式分類你的數(shù)據(jù)。下列例子顯示出進(jìn)行動物普查操作的不同方式。
每種動物的數(shù)量:
mysql> SELECT species, COUNT(*) FROM pet GROUP BY species; +---------+----------+ | species | COUNT(*) | +---------+----------+ | bird??? |??????? 2 | | cat???? |??????? 2 | | dog???? |??????? 3 | | hamster |??????? 1 | | snake?? |??????? 1 | +---------+----------+每種性別的動物數(shù)量:
mysql> SELECT sex, COUNT(*) FROM pet GROUP BY sex; +------+----------+ | sex? | COUNT(*) | +------+----------+ | NULL |??????? 1 | | f??? |??????? 4 | | m??? |??????? 4 | +------+----------+(在這個輸出中,NULL表示“未知性別”。)
按種類和性別組合的動物數(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( ),你不必檢索整個表。例如,?前面的查詢,當(dāng)只對狗和貓進(jìn)行時,應(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 | +---------+------+----------+或,如果你僅需要知道已知性別的按性別的動物數(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 | +---------+------+----------+ 3.3.4.9.?使用1個以上的表
?
pet表追蹤你有哪個寵物。如果你想要記錄其它相關(guān)信息,例如在他們一生中看獸醫(yī)或何時后代出生,你需要另外的表。這張表應(yīng)該像什么呢?需要: ·?????????它需要包含寵物名字以便你知道每個事件屬于哪個動物。
·?????????需要一個日期以便你知道事件是什么時候發(fā)生的。
·?????????需要一個描述事件的字段。
·?????????如果你想要對事件進(jìn)行分類,則需要一個事件類型字段。
綜合上述因素,event表的CREATE TABLE語句應(yīng)為:
mysql> CREATE TABLE event (name VARCHAR(20), date DATE, ??? -> type VARCHAR(15), remark VARCHAR(255));對于pet表,最容易的方法是創(chuàng)建包含信息的用定位符分隔的文本文件來裝載初始記錄:
| name | date | type | remark |
| Fluffy | 1995-05-15 | litter | 4 kittens, 3 female, 1 male |
| Buffy | 1993-06-23 | litter | 5 puppies, 2 female, 3 male |
| Buffy | 1994-06-19 | litter | 3 puppies, 3 female |
| Chirpy | 1999-03-21 | vet | needed beak straightened |
| Slim | 1997-08-03 | vet | broken rib |
| Bowser | 1991-10-12 | kennel | ? |
| Fang | 1991-10-12 | kennel | ? |
| Fang | 1998-08-28 | birthday | Gave him a new chew toy |
| Claws | 1998-03-17 | birthday | Gave him a new flea collar |
| Whistler | 1998-12-09 | birthday | First birthday |
采用如下方式裝載記錄:
mysql> LOAD DATA LOCAL INFILE 'event.txt' INTO TABLE event;根據(jù)你從已經(jīng)運行在pet表上的查詢中學(xué)到的,你應(yīng)該能執(zhí)行對event表中記錄的檢索;原理是一樣的。但是什么時候event表本身不能回答你可能問的問題呢?
當(dāng)他們有了一窩小動物時,假定你想要找出每只寵物的年齡。我們前面看到了如何通過兩個日期計算年齡。event表中有母親的生產(chǎn)日期,但是為了計算母親的年齡,你需要她的出生日期,存儲在pet表中。說明查詢需要兩個表:
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)于該查詢要注意的幾件事情:
- FROM子句列出兩個表,因為查詢需要從兩個表提取信息。
- 當(dāng)從多個表組合(聯(lián)結(jié))信息時,你需要指定一個表中的記錄怎樣能匹配其它表的記錄。這很簡單,因為它們都有一個name列。查詢使用WHERE子句基于name值來匹配2個表中的記錄。
- 因為name列出現(xiàn)在兩個表中,當(dāng)引用列時,你一定要指定哪個表。把表名附在列名前即可以實現(xiàn)。
你不必有2個不同的表來進(jìn)行聯(lián)結(jié)。如果你想要將一個表的記錄與同一個表的其它記錄進(jìn)行比較,可以將一個表聯(lián)結(jié)到自身。例如,為了在你的寵物之中繁殖配偶,你可以用pet聯(lián)結(jié)自身來進(jìn)行相似種類的雄雌配對:
?
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???? | +--------+------+--------+------+---------+在這個查詢中,我們?yōu)楸砻付▌e名以便能引用列并且使得每一個列引用與哪個表實例相關(guān)聯(lián)更直觀。
3.4.?獲得數(shù)據(jù)庫和表的信息
如果你忘記數(shù)據(jù)庫或表的名字,或給定的表的結(jié)構(gòu)是什么(例如,它的列叫什么),怎么辦?MySQL通過提供數(shù)據(jù)庫及其支持的表的信息的幾個語句解決這個問題。你已經(jīng)見到了SHOW DATABASES,它列出由服務(wù)器管理的數(shù)據(jù)庫。為了找出當(dāng)前選擇了哪個數(shù)據(jù)庫,使用DATABASE( )函數(shù):
mysql> SELECT DATABASE(); +------------+ | DATABASE() | +------------+ | menagerie? | +------------+如果你還沒選擇任何數(shù)據(jù)庫,結(jié)果是NULL。
為了找出當(dāng)前的數(shù)據(jù)庫包含什么表(例如,當(dāng)你不能確定一個表的名字),使用這個命令:
mysql> SHOW TABLES; +---------------------+ | Tables in menagerie | +---------------------+ | event?????????????? | | pet???????????????? | +---------------------+如果你想要知道一個表的結(jié)構(gòu),可以使用DESCRIBE命令;它顯示表中每個列的信息:
mysql> DESCRIBE pet; +---------+-------------+------+-----+---------+-------+ | Field?? | Type??????? | Null | Key | Default | Extra | +---------+-------------+------+-----+---------+-------+ | name??? | varchar(20) | YES? |???? | NULL??? |?????? | | owner?? | varchar(20) | YES? |???? | NULL??? |?????? | | species | varchar(20) | YES? |???? | NULL??? |??? ???| | sex???? | char(1)???? | YES? |???? | NULL??? |?????? | | birth?? | date??????? | YES? |???? | NULL??? |?????? | | death?? | date??????? | YES? |???? | NULL??? |?????? | +---------+-------------+------+-----+---------+-------+Field顯示列名字,Type是列的數(shù)據(jù)類型,Null表示列是否能包含NULL值,Key顯示列是否被索引而Default指定列的默認(rèn)值。
如果表有索引,SHOW INDEX FROM tbl_name生成有關(guān)索引的信息。
3.5.?在批處理模式下使用mysql
在前面的章節(jié)中,你交互式地使用mysql輸入查詢并且查看結(jié)果。你也可以以批模式運行mysql。為了做到這些,把你想要運行的命令放在一個文件中,然后告訴mysql從文件讀取它的輸入:shell> mysql < batch-file如果在Windows下運行mysql,并且文件中有一些可以造成問題的特殊字符,可以這樣操作:
C:/> mysql -e "source batch-file"如果你需要在命令行上指定連接參數(shù),命令應(yīng)為:
shell> mysql -h host -u user -p < batch-file Enter password: ********當(dāng)這樣操作mysql時,則創(chuàng)建一個腳本文件,然后執(zhí)行腳本。
如果你想在語句出現(xiàn)錯誤的時候仍想繼續(xù)執(zhí)行腳本,則應(yīng)使用--force命令行選項。
為什么要使用一個腳本?有很多原因:
- 如果你需要重復(fù)運行查詢(比如說,每天或每周),可以把它編成一個腳本,則每次執(zhí)行時不必重新鍵入。
- 可以通過拷貝并編輯腳本文件從類似的現(xiàn)有的查詢生成一個新查詢。
- 當(dāng)你正在開發(fā)查詢時,批模式也是很有用的,特別對多行命令或多語句命令序列。如果你犯了一個錯誤,你不必重新輸入所有內(nèi)容,只需要編輯腳本來改正錯誤,然后告訴mysql再次執(zhí)行腳本。
- 如果你有一個產(chǎn)生多個輸出的查詢,你可以通過一個分頁器而不是盯著它翻屏到屏幕的頂端來運行輸出:
- 你可以捕捉文件中的輸出以便進(jìn)行進(jìn)一步的處理:
- 你可以將腳本分發(fā)給另外的人,以便他們也能運行命令。
- 某些情況不允許交互地使用,例如,?當(dāng)你從一個cron任務(wù)中運行查詢時。在這種情況下,你必須使用批模式。
當(dāng)你以批模式運行mysql時,比起你交互地使用它時,其默認(rèn)輸出格式是不同的(更簡明些)。例如,當(dāng)交互式運行SELECT DISTINCT species FROM pet時,輸出應(yīng)為:
?
+---------+ | species | +---------+ | bird??? | | cat???? | | dog???? | | hamster | | snake?? | +---------+但是當(dāng)以批模式運行時,輸出應(yīng)為:
species bird cat dog hamster snake如果你想要在批模式中得到交互輸出格式,使用mysql -t。為了回顯以輸出被執(zhí)行的命令,使用mysql -vvv。
你還可以使用源代碼或?/.命令從mysql提示符運行腳本:
mysql> source filename; mysql> /. filename3.6.?常用查詢的例子
3.6.1. 列的最大值3.6.2. 擁有某個列的最大值的行3.6.3. 列的最大值:按組3.6.4. 擁有某個字段的組間最大值的行3.6.5. 使用用戶變量3.6.6. 使用外鍵3.6.7. 根據(jù)兩個鍵搜索3.6.8. 根據(jù)天計算訪問量3.6.9. 使用AUTO_INCREMENT下面是一些學(xué)習(xí)如何用MySQL解決一些常見問題的例子。
在一些例子中,使用數(shù)據(jù)庫表“shop”來儲存某個商人(經(jīng)銷商)的每件物品(物品號)的價格。假定每個商人對每項物品有一個固定價格,那么(物品,商人)即為該記錄的主關(guān)鍵字。
啟動命令行工具mysql并選擇數(shù)據(jù)庫:
shell> mysql your-database-name(在大多數(shù)MySQL中,你可以使用test數(shù)據(jù)庫)。
你可以使用以下語句創(chuàng)建示例表:
mysql> CREATE TABLE shop ( ??? -> article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL, ??? -> dealer? CHAR(20)???????????????? DEFAULT ''???? NOT NULL, ??? -> price?? DOUBLE(16,2)???????????? DEFAULT '0.00' NOT NULL, ??? -> PRIMARY KEY(article, dealer)); mysql> INSERT INTO shop VALUES ??? -> (1,'A',3.45),(1,'B',3.99),(2,'A',10.99),(3,'B',1.45), ??? -> (3,'C',1.69),(3,'D',1.25),(4,'D',19.95);執(zhí)行語句后,表應(yīng)包含以下內(nèi)容:
mysql> SELECT * FROM shop; +---------+--------+-------+ | article | dealer | price | +---------+--------+-------+ |??? 0001 | A????? |? 3.45 | |??? 0001 | B????? |? 3.99 | |??? 0002 | A????? | 10.99 | | ???0003 | B????? |? 1.45 | |??? 0003 | C????? |? 1.69 | |??? 0003 | D????? |? 1.25 | |??? 0004 | D????? | 19.95 | +---------+--------+-------+3.6.1.?列的最大值
“最大的物品號是什么?”
SELECT MAX(article) AS article FROM shop;+---------+ | article | +---------+ | 4 | +---------+3.6.2.?擁有某個列的最大值的行
任務(wù):找出最貴物品的編號、銷售商和價格。這很容易用一個子查詢做到:
SELECT article, dealer, price FROM?? shop WHERE? price=(SELECT MAX(price) FROM shop);另一個解決方案是按價格降序排序所有行并用MySQL特定LIMIT子句只得到第一行:
SELECT article, dealer, price FROM shop ORDER BY price DESC LIMIT 1;注:如果有多項最貴的物品(?例如每個的價格為19.95),LIMIT解決方案僅僅顯示其中一個!
3.6.3.?列的最大值:按組
任務(wù):每項物品的的最高價格是多少?
SELECT article, MAX(price) AS price FROM shop GROUP BY article+---------+-------+ | article | price | +---------+-------+ | 0001 | 3.99 | | 0002 | 10.99 | | 0003 | 1.69 | | 0004 | 19.95 | +---------+-------+3.6.4.?擁有某個字段的組間最大值的行
任務(wù):對每項物品,找出最貴價格的物品的經(jīng)銷商。
可以用這樣一個子查詢解決該問題:
SELECT article, dealer, price FROM shop s1 WHERE price=(SELECT MAX(s2.price)FROM shop s2WHERE s1.article = s2.article);3.6.5.?使用用戶變量
你可以清空MySQL用戶變量以記錄結(jié)果,不必將它們保存到客戶端的臨時變量中。(參見?9.3節(jié),“用戶變量”.)。
例如,要找出價格最高或最低的物品的,其方法是:
mysql> SELECT @min_price:=MIN(price),@max_price:=MAX(price) FROM shop; mysql> SELECT * FROM shop WHERE price=@min_price OR price=@max_price; +---------+--------+-------+ | article | dealer | price | +---------+--------+-------+ | 0003 | D | 1.25 | | 0004 | D | 19.95 | +---------+--------+-------+3.6.6.?使用外鍵
在MySQL中,InnoDB表支持對外部關(guān)鍵字約束條件的檢查。參見15.2節(jié),“InnoDB存儲引擎”。還可以參見1.8.5.5節(jié),“外鍵”。
只是聯(lián)接兩個表時,不需要外部關(guān)鍵字。對于除InnoDB類型的表,當(dāng)使用REFERENCES?tbl_name(col_name)子句定義列時可以使用外部關(guān)鍵字,該子句沒有實際的效果,只作為備忘錄或注釋來提醒,你目前正定義的列指向另一個表中的一個列。執(zhí)行該語句時,實現(xiàn)下面很重要:
·?????????MySQL不執(zhí)行表tbl_name?中的動作,例如作為你正定義的表中的行的動作的響應(yīng)而刪除行;換句話說,該句法不會致使ON DELETE或ON UPDATE行為(如果你在REFERENCES子句中寫入ON DELETE或ON UPDATE子句,將被忽略)。
·?????????該句法可以創(chuàng)建一個column;但不創(chuàng)建任何索引或關(guān)鍵字。
·?????????如果用該句法定義InnoDB表,將會導(dǎo)致錯誤。
你可以使用作為聯(lián)接列創(chuàng)建的列,如下所示:
CREATE TABLE person ( ??? id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, ??? name CHAR(60) NOT NULL, ??? PRIMARY KEY (id) ); ? CREATE TABLE shirt ( ??? id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, ??? style ENUM('t-shirt', 'polo', 'dress') NOT NULL, ??? color ENUM('red', 'blue', 'orange', 'white', 'black') NOT NULL, ??? owner SMALLINT UNSIGNED NOT NULL REFERENCES person(id), ??? PRIMARY KEY (id) ); ? INSERT INTO person VALUES (NULL, 'Antonio Paz'); ? SELECT @last := LAST_INSERT_ID(); ? INSERT INTO shirt VALUES (NULL, 'polo', 'blue', @last), (NULL, 'dress', 'white', @last), (NULL, 't-shirt', 'blue', @last); ? INSERT INTO person VALUES (NULL, 'Lilliana Angelovska'); ? SELECT @last := LAST_INSERT_ID(); ? INSERT INTO shirt VALUES (NULL, 'dress', 'orange', @last), (NULL, 'polo', 'red', @last), (NULL, 'dress', 'blue', @last), (NULL, 't-shirt', 'white', @last); ? SELECT * FROM person; +----+---------------------+ | id | name??????????????? | +----+---------------------+ |? 1 | Antonio Paz???????? | |? 2 | Lilliana Angelovska | +----+---------------------+ ? SELECT * FROM shirt; +----+---------+--------+-------+ | id | style?? | color? | owner | +----+---------+--------+-------+ |? 1 | polo??? | blue?? |???? 1 | |? 2 | dress?? | white? |???? 1 | |? 3 | t-shirt | blue?? |???? 1 | |? 4 | dress?? | orange |???? 2 | |? 5 | polo??? | red??? |???? 2 | |? 6 | dress?? | blue?? |???? 2 | |? 7 | t-shirt | white? |???? 2 | +----+---------+--------+-------+ ? ? SELECT s.* FROM person p, shirt s WHERE p.name LIKE 'Lilliana%' ?? AND s.owner = p.id ?? AND s.color <> 'white'; ? +----+-------+--------+-------+ | id | style | color? | owner | +----+-------+--------+-------+ |? 4 | dress | orange |???? 2 | |? 5 | polo? | red??? |???? 2 | |? 6 | dress | blue?? |???? 2 | +----+-------+--------+-------+按照這種方式使用,REFERENCES子句不會顯示在SHOW CREATE TABLE或DESCRIBE的輸出中:
SHOW CREATE TABLE shirt/G *************************** 1. row *************************** Table: shirt Create Table: CREATE TABLE `shirt` ( `id` smallint(5) unsigned NOT NULL auto_increment, `style` enum('t-shirt','polo','dress') NOT NULL, `color` enum('red','blue','orange','white','black') NOT NULL, `owner` smallint(5) unsigned NOT NULL, PRIMARY KEY? (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1在列定義中,按這種方式使用REFERENCES作為注釋或“提示”適用于表MyISAM和BerkeleyDB。
3.6.7.?根據(jù)兩個鍵搜索
可以充分利用使用單關(guān)鍵字的OR子句,如同AND的處理。
一個比較靈活的例子是尋找兩個通過OR組合到一起的關(guān)鍵字:
SELECT field1_index, field2_index FROM test_table WHERE field1_index = '1' OR? field2_index = '1'該情形是已經(jīng)優(yōu)化過的。參見7.2.6節(jié),“索引合并優(yōu)化”。
還可以使用UNION將兩個單獨的SELECT語句的輸出合成到一起來更有效地解決該問題。參見13.2.7.2節(jié),“UNION語法
”。
每個SELECT只搜索一個關(guān)鍵字,可以進(jìn)行優(yōu)化:
SELECT field1_index, field2_index ??? FROM test_table WHERE field1_index = '1' UNION SELECT field1_index, field2_index ? ??FROM test_table WHERE field2_index = '1';3.6.8.?根據(jù)天計算訪問量
下面的例子顯示了如何使用位組函數(shù)來計算每個月中用戶訪問網(wǎng)頁的天數(shù)。
CREATE TABLE t1 (year YEAR(4), month INT(2) UNSIGNED ZEROFILL, ???????????? day INT(2) UNSIGNED ZEROFILL); INSERT INTO t1 VALUES(2000,1,1),(2000,1,20),(2000,1,30),(2000,2,2), ??????????? (2000,2,23),(2000,2,23);示例表中含有代表用戶訪問網(wǎng)頁的年-月-日值。可以使用以下查詢來確定每個月的訪問天數(shù):
SELECT year,month,BIT_COUNT(BIT_OR(1<<day)) AS days FROM t1 ?????? GROUP BY year,month;將返回:
+------+-------+------+ | year | month | days | +------+-------+------+ | 2000 |??? 01 |??? 3 | | 2000 |??? 02 |??? 2 | +------+-------+------+該查詢計算了在表中按年/月組合的不同天數(shù),可以自動去除重復(fù)的詢問。
3.6.9.?使用AUTO_INCREMENT
可以通過AUTO_INCREMENT屬性為新的行產(chǎn)生唯一的標(biāo)識:
CREATE TABLE animals ( ???? id MEDIUMINT NOT NULL AUTO_INCREMENT, ???? name CHAR(30) NOT NULL, ???? PRIMARY KEY (id) ); ? INSERT INTO animals (name) VALUES ????('dog'),('cat'),('penguin'), ??? ('lax'),('whale'),('ostrich'); ? SELECT * FROM animals;將返回:
+----+---------+ | id | name??? | +----+---------+ |? 1 | dog???? | |? 2 | cat???? | |? 3 | penguin | |? 4 | lax???? | |? 5 | whale?? | |? 6 | ostrich | +----+---------+你可以使用LAST_INSERT_ID()SQL函數(shù)或mysql_insert_id()?C API函數(shù)來查詢最新的AUTO_INCREMENT值。這些函數(shù)與具體連接有關(guān),因此其返回值不會被其它執(zhí)行插入功能的連接影響。
注釋:對于多行插入,LAST_INSERT_ID()和mysql_insert_id()從插入的第一行實際返回AUTO_INCREMENT關(guān)鍵字。在復(fù)制設(shè)置中,通過該函數(shù)可以在其它服務(wù)器上正確復(fù)制多行插入。
對于MyISAM和BDB表,你可以在第二欄指定AUTO_INCREMENT以及多列索引。此時,AUTO_INCREMENT列生成的值的計算方法為:MAX(auto_increment_column) + 1 WHERE prefix=given-prefix。如果想要將數(shù)據(jù)放入到排序的組中可以使用該方法。
CREATE TABLE animals ( ??? grp ENUM('fish','mammal','bird') NOT NULL, ??? id MEDIUMINT NOT NULL AUTO_INCREMENT, ??? name CHAR(30) NOT NULL, ??? PRIMARY KEY (grp,id) ); ? INSERT INTO animals (grp,name) VALUES ????('mammal','dog'),('mammal','cat'), ??? ('bird','penguin'),('fish','lax'),('mammal','whale'), ??? ('bird','ostrich'); ? SELECT * FROM animals ORDER BY grp,id;將返回:
+--------+----+---------+ | grp??? | id | name??? | +--------+----+---------+ | fish?? |? 1 | lax???? | | mammal |? 1 | dog???? | | mammal |? 2 | cat???? | | mammal |? 3 | whale?? | | bird?? |? 1 | penguin | | bird?? |? 2 | ostrich | +--------+----+---------+請注意在這種情況下(AUTO_INCREMENT列是多列索引的一部分),如果你在任何組中刪除有最大AUTO_INCREMENT值的行,將會重新用到AUTO_INCREMENT值。對于MyISAM表也如此,對于該表一般不重復(fù)使用AUTO_INCREMENT值。
如果AUTO_INCREMENT列是多索引的一部分,MySQL將使用該索引生成以AUTO_INCREMENT列開始的序列值。。例如,如果animals表含有索引PRIMARY KEY (grp, id)和INDEX(id),MySQL生成序列值時將忽略PRIMARY KEY。結(jié)果是,該表包含一個單個的序列,而不是符合grp值的序列。
要想以AUTO_INCREMENT值開始而不是1,你可以通過CREATE TABLE或ALTER TABLE來設(shè)置該值,如下所示:
mysql> ALTER TABLE tbl AUTO_INCREMENT = 100;關(guān)于AUTO_INCREMENT的詳細(xì)信息:
·?????????如何為列指定AUTO_INCREMENT屬性:13.1.5節(jié),“CREATE TABLE語法”和?13.1.2節(jié),“ALTER TABLE語法”。
·?????????AUTO_INCREMENT的動作取決于SQL模式:5.3.2節(jié),“SQL服務(wù)器模式”。
·?????????找出含有最新AUTO_INCREMENT值的行:12.1.3節(jié),“比較函數(shù)和操作符”。
·?????????設(shè)置將用到的AUTO_INCREMENT值:?13.5.3節(jié),“SET語法”?。
·?????????AUTO_INCREMENT和復(fù)制:6.7節(jié),“復(fù)制特性和已知問題”.
·?????????AUTO_INCREMENT相關(guān)的可用于復(fù)制的Server-system變量(auto_increment_increment和auto_increment_offset):5.3.3節(jié),“服務(wù)器系統(tǒng)變量”。
?
3.7.?孿生項目的查詢
3.7.1. 查找所有未分發(fā)的孿生項3.7.2. 顯示孿生對狀態(tài)的表這個項目是Institute of Environmental Medicine at Karolinska Institutet Stockholm?和?the Section on Clinical Research in Aging and Psychology at the University of Southern California的合作項目。
該項目包括篩選部分,即通過電話回訪在瑞典超過?65?歲的所有孿生。滿足某種標(biāo)準(zhǔn)的孿生進(jìn)入下一階段。在下一階段中,醫(yī)生/護(hù)士小組將訪問想?yún)⒓拥膶\生。部分檢查包括物理檢查和神經(jīng)、心理檢查、實驗室試驗、神經(jīng)成像、心理狀況評估和家族歷史搜集。并且,應(yīng)根據(jù)醫(yī)療和環(huán)境風(fēng)險因素來搜集數(shù)據(jù)。
可從以下鏈接找到孿生研究的更多信息:
http://www.mep.ki.se/twinreg/index_en.html
用一個用Perl和MySQL編寫的web接口來管理項目的后面部分。
每天晚上所有會談的數(shù)據(jù)被移入一個MySQL數(shù)據(jù)庫。
3.7.1.?查找所有未分發(fā)的孿生項
下列查詢用來決定誰進(jìn)入項目的第二部分:
SELECTCONCAT(p1.id, p1.tvab) + 0 AS tvid,CONCAT(p1.christian_name, ' ', p1.surname) AS Name,p1.postal_code AS Code,p1.city AS City,pg.abrev AS Area,IF(td.participation = 'Aborted', 'A', ' ') AS A,p1.dead AS dead1,l.event AS event1,td.suspect AS tsuspect1,id.suspect AS isuspect1,td.severe AS tsevere1,id.severe AS isevere1,p2.dead AS dead2,l2.event AS event2,h2.nurse AS nurse2,h2.doctor AS doctor2,td2.suspect AS tsuspect2,id2.suspect AS isuspect2,td2.severe AS tsevere2,id2.severe AS isevere2,l.finish_date FROMtwin_project AS tp/* For Twin 1 */LEFT JOIN twin_data AS td ON tp.id = td.idAND tp.tvab = td.tvabLEFT JOIN informant_data AS id ON tp.id = id.idAND tp.tvab = id.tvabLEFT JOIN harmony AS h ON tp.id = h.idAND tp.tvab = h.tvabLEFT JOIN lentus AS l ON tp.id = l.idAND tp.tvab = l.tvab/* For Twin 2 */LEFT JOIN twin_data AS td2 ON p2.id = td2.idAND p2.tvab = td2.tvabLEFT JOIN informant_data AS id2 ON p2.id = id2.idAND p2.tvab = id2.tvabLEFT JOIN harmony AS h2 ON p2.id = h2.idAND p2.tvab = h2.tvabLEFT JOIN lentus AS l2 ON p2.id = l2.idAND p2.tvab = l2.tvab,person_data AS p1,person_data AS p2,postal_groups AS pg WHERE/* p1 gets main twin and p2 gets his/her twin. *//* ptvab is a field inverted from tvab */p1.id = tp.id AND p1.tvab = tp.tvab ANDp2.id = p1.id AND p2.ptvab = p1.tvab AND/* Just the screening survey */tp.survey_no = 5 AND/* Skip if partner died before 65 but allow emigration (dead=9) */(p2.dead = 0 OR p2.dead = 9 OR(p2.dead = 1 AND(p2.death_date = 0 OR(((TO_DAYS(p2.death_date) - TO_DAYS(p2.birthday)) / 365)>= 65))))AND(/* Twin is suspect */(td.future_contact = 'Yes' AND td.suspect = 2) OR/* Twin is suspect - Informant is Blessed */(td.future_contact = 'Yes' AND td.suspect = 1AND id.suspect = 1) OR/* No twin - Informant is Blessed */(ISNULL(td.suspect) AND id.suspect = 1AND id.future_contact = 'Yes') OR/* Twin broken off - Informant is Blessed */(td.participation = 'Aborted'AND id.suspect = 1 AND id.future_contact = 'Yes') OR/* Twin broken off - No inform - Have partner */(td.participation = 'Aborted' AND ISNULL(id.suspect)AND p2.dead = 0))ANDl.event = 'Finished'/* Get at area code */AND SUBSTRING(p1.postal_code, 1, 2) = pg.code/* Not already distributed */AND (h.nurse IS NULL OR h.nurse=00 OR h.doctor=00)/* Has not refused or been aborted */AND NOT (h.status = 'Refused' OR h.status = 'Aborted'OR h.status = 'Died' OR h.status = 'Other') ORDER BYtvid;一些解釋:
·?????????CONCAT(p1.id, p1.tvab) + 0 AS tvid
我們想要在id和tvab的連接上以數(shù)字順序排序。結(jié)果加0使得MySQL把結(jié)果變?yōu)橐粋€數(shù)字。
·?????????列id
這標(biāo)識一對孿生。它是所有表中的一個鍵。
·?????????列tvab
這標(biāo)識孿生中的一個。它的值為1或2。
·?????????列ptvab
這是tvab的一個逆運算。當(dāng)tvab是1,它是2,反之亦然。它用來保存輸入并且使MySQL的優(yōu)化查詢更容易。
這個查詢表明,怎樣用聯(lián)結(jié)(p1和p2)從同一個表中查找表。在例子中,這被用來檢查孿生的一個是否在65歲前死了。如果如此,行不返回值。
上述所有孿生信息存在于所有表中。我們對id,tvab(所有表)和id,ptvab?(person_data)?上采用鍵以使查詢更快。
在我們的生產(chǎn)機(jī)器上(一臺200MHz UltraSPARC),這個查詢返回大約?150-200?行并且時間不超過一秒。
| 表 | 行數(shù) |
| person_data | 71074 |
| lentus | 5291 |
| twin_project | 5286 |
| twin_data | 2012 |
| informant_data | 663 |
| harmony | 381 |
| postal_groups | 100 |
3.7.2.?顯示孿生對狀態(tài)的表
每一次會面以一個稱為event的狀態(tài)碼結(jié)束。下面顯示的查詢被用來顯示按事件組合的所有孿生的表。這表明多少對孿生已經(jīng)完成,多少對的其中之一已完成而另一個拒絕了,等等。SELECT ??????? t1.event, ??????? t2.event, ??????? COUNT(*) FROM ??????? lentus AS t1, ??????? lentus AS t2, ??????? twin_project AS tp WHERE ??????? /* We are looking at one pair at a time */ ??????? t1.id = tp.id ??????? AND t1.tvab=tp.tvab ??????? AND t1.id = t2.id ??????? /* Just the screening survey */ ??????? AND tp.survey_no = 5 ??????? /* This makes each pair only appear once */ ??????? AND t1.tvab='1' AND t2.tvab='2' GROUP BY ??????? t1.event, t2.event;3.8.?與Apache一起使用MySQL
還有一些項目,你可以從MySQL數(shù)據(jù)庫鑒別用戶,并且你還可以將日志文件寫入MySQL數(shù)據(jù)庫表。你可以將以下內(nèi)容放到Apache配置文件中,更改Apache日志格式,使MySQL更容易讀取:
LogFormat / ??????? "/"%h/",%{%Y%m%d%H%M%S}t,%>s,/"%b/",/"%{Content-Type}o/",? / ??????? /"%U/",/"%{Referer}i/",/"%{User-Agent}i/""要想將該格式的日志文件裝載到MySQL,你可以使用以下語句:
LOAD DATA INFILE '/local/access_log' INTO TABLE tbl_name FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' ESCAPED BY '//'所創(chuàng)建的表中的列應(yīng)與寫入日志文件的LogFormat行對應(yīng)。
這是MySQL參考手冊的翻譯版本,關(guān)于MySQL參考手冊,請訪問dev.mysql.com。 原始參考手冊為英文版,與英文版參考手冊相比,本翻譯版可能不是最新的。
本文轉(zhuǎn)自天天_byconan博客園博客,原文鏈接:http://www.cnblogs.com/tiantianbyconan/archive/2012/07/08/2581684.html,如需轉(zhuǎn)載請自行聯(lián)系原作者總結(jié)
以上是生活随笔為你收集整理的mysql 基本使用教程(源于网络)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java多线程系列--“JUC原子类”0
- 下一篇: cmd MySQL登录