|
本章通過演示如何使用MySQL客戶程序創(chuàng)造和使用一個簡單的數(shù)據(jù)庫,提供一個MySQL的入門教程。MySQL(有時稱為“終端監(jiān)視器”或只是“監(jiān)視”)是一個交互式程序,允許你連接一個MySQL服務(wù)器,運(yùn)行查詢并察看結(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管理員。 本章描述建立和使用一個數(shù)據(jù)庫的全過程。如果你僅僅對訪問一個已經(jīng)存在的數(shù)據(jù)庫感興趣,可以跳過描述怎樣創(chuàng)建數(shù)據(jù)庫及它所包含的表的章節(jié)。 由于本章是一個教程,省略了許多細(xì)節(jié)。關(guān)于這里所涉及的主題的詳細(xì)信息,請查閱本手冊的相關(guān)章節(jié)。 1. 連接與斷開服務(wù)器 為了連接服務(wù)器,當(dāng)調(diào)用mysql時,通常需要提供一個MySQL用戶名并且很可能需要一個 密碼。如果服務(wù)器運(yùn)行在登錄服務(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ù)器運(yùn)行的主機(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ī)上運(yùn)行的服務(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>提示指明。 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é)束。 | `> | 等待下一行,等待以反斜點(diǎn)(‘`’)開始的識別符的結(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. 創(chuàng)建并使用數(shù)據(jù)庫 3.1. 創(chuàng)建并選擇數(shù)據(jù)庫 3.2. 創(chuàng)建表 3.3. 將數(shù)據(jù)裝入表中 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ù)庫的真實(shí)世界情況。例如,農(nóng)夫可以使用這樣的一個數(shù)據(jù)庫來追蹤家畜,或者獸醫(yī)可以用它跟蹤病畜記錄。從MySQL網(wǎng)址上可以獲得后面章節(jié)中將用到的含有部分查詢和樣例數(shù)據(jù)的動物園分發(fā)。有tar壓縮格式 ()和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ù)庫。參見 “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.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語句來實(shí)現(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.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提供了日期運(yùn)算函數(shù),因此這并不困難。存儲出生日期而非年齡還有其它優(yōu)點(diǎn): ·你可以使用數(shù)據(jù)庫完成這樣的任務(wù),例如生成即將到來的寵物生日的提示。(如果你認(rèn)為這類查詢有點(diǎ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. 將數(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中的編輯器(使用
做為行的結(jié)束符)創(chuàng)建文件,應(yīng)使用: MySQL> LOAD DATA LOCAL INFILE '/path/pet.txt' INTO TABLE pet -> LINES TERMINATED BY '
'; (在運(yùn)行OS X的Apple機(jī)上,應(yīng)使用行結(jié)束符'
'。) 如果你愿意,你能明確地在LOAD DATA語句中指出列值的分隔符和行尾標(biāo)記,但是默認(rèn)標(biāo)記是定位符和換行符。這對讀入文件“pet.txt”的語句已經(jīng)足夠。 如果該語句失敗,可能是你安裝的MySQL不與使用默認(rèn)值的本地文件兼容。關(guān)于如何更改請參見“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.4. 從表檢索信息 3.4.1. 選擇所有數(shù)據(jù) 3.4.2. 選擇特殊行 3.4.3. 選擇特殊列 3.4.4. 分類行 3.4.5. 日期計算 3.4.6. NULL值操作 3.4.7. 模式匹配 3.4.8. 計數(shù)行 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.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.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 | +--------+-------+---------+------+------------+------------+ 輸出證實(shí)正確的年份記錄為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.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.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.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ù)。為了看它怎樣工作,運(yù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 | +----------+------------+--------------+ 找出下個月生日的動物也是容易的。假定當(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月,就有點(diǎn)復(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.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意味著假而其它值意味著真。布爾運(yùn)算的默認(rèn)真值是1。 對NULL的特殊處理即是在前面的章節(jié)中,為了決定哪個動物不再是活著的,使用death IS NOT NULL而不使用death != NULL的原因。 在GROUP BY中,兩個NULL值視為相同。 執(zhí)行ORDER BY時,如果運(yùn)行 ORDER BY ... ASC,則NULL值出現(xiàn)在最前面,若運(yùn)行ORDER BY ... DESC,則NULL值出現(xiàn)在最后面。 NULL操作的常見錯誤是不能在定義為NOT NULL的列內(nèi)插入0或空字符串,但事實(shí)并非如此。在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或空字符串,實(shí)際是NOT NULL。參見A.5.3節(jié),“與NULL值有關(guān)的問題”。 3.4.7. 模式匹配 MySQL提供標(biāo)準(zhǔn)的SQL模式匹配,以及一種基于象Unix實(shí)用程序如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個“.”實(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次”操作符重寫前面的查詢: 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.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 clause COUNT( )和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.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)運(yùn)行在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)引用列時,你一定要指定哪個表。把表名附在列名前即可以實(shí)現(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名以便能引用列并且使得每一個列引用與哪個表實(shí)例相關(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é)果。你也可以以批模式運(yùn)行MySQL。為了做到這些,把你想要運(yùn)行的命令放在一個文件中,然后告訴MySQL從文件讀取它的輸入: shell> mysql < batch-file 如果在Windows下運(yùn)行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ù)運(yùn)行查詢(比如說,每天或每周),可以把它編成一個腳本,則每次執(zhí)行時不必重新鍵入。 可以通過拷貝并編輯腳本文件從類似的現(xiàn)有的查詢生成一個新查詢。 當(dāng)你正在開發(fā)查詢時,批模式也是很有用的,特別對多行命令或多語句命令序列。如果你犯了一個錯誤,你不必重新輸入所有內(nèi)容,只需要編輯腳本來改正錯誤,然后告訴mysql再次執(zhí)行腳本。 如果你有一個產(chǎn)生多個輸出的查詢,你可以通過一個分頁器而不是盯著它翻屏到屏幕的頂端來運(yùn)行輸出: ·shell> MySQL < batch-file | more 你可以捕捉文件中的輸出以便進(jìn)行進(jìn)一步的處理: ·shell> MySQL < batch-file > MySQL.out 你可以將腳本分發(fā)給另外的人,以便他們也能運(yùn)行命令。 某些情況不允許交互地使用,例如, 當(dāng)你從一個cron任務(wù)中運(yùn)行查詢時。在這種情況下,你必須使用批模式。 當(dāng)你以批模式運(yùn)行mysql時,比起你交互地使用它時,其默認(rèn)輸出格式是不同的(更簡明些)。例如,當(dāng)交互式運(yùn)行SELECT DISTINCT species FROM pet時,輸出應(yīng)為: +---------+ | species | +---------+ | bird | | cat | | dog | | hamster | | snake | +---------+ 但是當(dāng)以批模式運(yùn)行時,輸出應(yīng)為: species bird cat dog hamster snake 如果你想要在批模式中得到交互輸出格式,使用mysql -t。為了回顯以輸出被執(zhí)行的命令,使用mysql -vvv。 你還可以使用源代碼或 .命令從mysql提示符運(yùn)行腳本: mysql> source filename; mysql> . filename 3.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)鍵字。 啟動命令行工具M(jìn)ySQL并選擇數(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 s2 WHERE s1.article = s2.article); 3.6.5. 使用用戶變量 你可以清空MySQL用戶變量以記錄結(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)鍵字,該子句沒有實(shí)際的效果,只作為備忘錄或注釋來提醒,你目前正定義的列指向另一個表中的一個列。執(zhí)行該語句時,實(shí)現(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 shirtG *************************** 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將兩個單獨(dú)的SELECT語句的輸出合成到一起來更有效地解決該問題。參見“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()從插入的第一行實(shí)際返回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屬性:“CREATE TABLE語法”和,“ALTER TABLE語法”。 ·AUTO_INCREMENT的動作取決于SQL模式:“SQL服務(wù)器模式”。 ·找出含有最新AUTO_INCREMENT值的行:“比較函數(shù)和操作符”。 ·設(shè)置將用到的AUTO_INCREMENT值: “SET語法” 。 ·AUTO_INCREMENT和復(fù)制:6.7節(jié),“復(fù)制特性和已知問題”. ·AUTO_INCREMENT相關(guān)的可用于復(fù)制的Server-system變量(auto_increment_increment和auto_increment_offset):“服務(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)、心理檢查、實(shí)驗室試驗、神經(jīng)成像、心理狀況評估和家族歷史搜集。并且,應(yīng)根據(jù)醫(yī)療和環(huán)境風(fēng)險因素來搜集數(shù)據(jù)。 可從以下鏈接找到孿生研究的更多信息: 用一個用Perl和MySQL編寫的web接口來管理項目的后面部分。 每天晚上所有會談的數(shù)據(jù)被移入一個MySQL數(shù)據(jù)庫。 3.7.1. 查找所有未分發(fā)的孿生項 下列查詢用來決定誰進(jìn)入項目的第二部分: SELECT CONCAT(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 FROM twin_project AS tp /* For Twin 1 */ LEFT JOIN twin_data AS td ON tp.id = td.id AND tp.tvab = td.tvab LEFT JOIN informant_data AS id ON tp.id = id.id AND tp.tvab = id.tvab LEFT JOIN harmony AS h ON tp.id = h.id AND tp.tvab = h.tvab LEFT JOIN lentus AS l ON tp.id = l.id AND tp.tvab = l.tvab /* For Twin 2 */ LEFT JOIN twin_data AS td2 ON p2.id = td2.id AND p2.tvab = td2.tvab LEFT JOIN informant_data AS id2 ON p2.id = id2.id AND p2.tvab = id2.tvab LEFT JOIN harmony AS h2 ON p2.id = h2.id AND p2.tvab = h2.tvab LEFT JOIN lentus AS l2 ON p2.id = l2.id AND 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 AND p2.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 = 1 AND id.suspect = 1) OR /* No twin - Informant is Blessed */ (ISNULL(td.suspect) AND id.suspect = 1 AND id.future_contact = 'Yes') OR /* Twin broken off - Informant is Blessed */ (td.participation = 'Aborted' AND id.suspect = 1 AND id.future_contact = 'Yes') OR
信息發(fā)布:廣州名易軟件有限公司 http://www.jetlc.com
|