本篇文章將介紹MySQL的相關知識,通過展示如何藉助mysql客戶端用程序指令創建和使用一個簡單的數據可。mysql(MySQL命令行工具)是一個交互式程序指令工具,你可以藉此連接到MySQL數據庫、執行查詢並且瀏覽查詢結果。mysql允許你使用批處理模式:預先將查詢指令存入文件內,然後告訴mysql來執行文件的內容。兩種使用mysql的方法在文本中都會介紹到。
有時候你需要查看mysql都為我們提供了那些參數,只需要使用*--help*參數得到mysql的參數列表。
shell> mysql --help
在本面文章正式開始之前,你需要確保mysql已經正確的安裝到了你的機器上並且可以連接到MySQL服務,如果你的答案是否定的,請前往MySQL官網。
1、建立和斷開數據庫服務連接
為了成功連接到MySQL服務,你通常需要提供MySQL用戶名和密碼,如果MySQL服務不是在執行登錄命令的主機上,你還需要制定一個遠程主機名。
shell> mysql -h host -u user -pEnter password: ******
host和user代表運行MySQL服務的主機名和MySQL賬號的用戶名,當mysql提示你需要輸入密碼時,鍵入密碼即可。
如果上一步起作用了,你將看到一些提示信息,並且進入mysql上下文。
shell> mysql -h host -u user -pEnter password: ********Welcome to the MySQL monitor. Commands end with ; or \g.Your MySQL connection id is 25338 to server version: 5.7.21-standardType 'help;' or '\h' for help. Type '\c' to clear the buffer.mysql>
mysql>prompt 表示mysql已經準備好你來鍵入SQL語句。
如果你登錄MySQL的機器和運行MySQL服務的在同一臺機器上,你可以省略主機,簡化代碼:
shell> mysql -u user -p
然而,如果你在嘗試登錄時,得到一個錯誤的提示信息,類似於:
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
這意味著MySQL服務沒有運行。前往 Chapter 2, Installing and Upgrading MySQL獲得幫助。
如果遇到其他問題,前往Section B.5.2, “Common Errors When Using MySQL Programs”獲取幫助。
一些MySQL服務允許了用戶以匿名(無用戶名)的方式連接到本地運行的服務。你可以使用以下無任何參數的指令:
shell> mysql
在你成功與MySQL服務建立連接後,你可以使用QUIT(或者\q)隨時斷開連接連接:
mysql> QUITBye
在Unix系統中,你也可以通過鍵入 Control+D 斷開連接。
本文以下例子中,假設你已經連接到了MySQL服務。
2、查詢
確保你已經連接到MySQL服務,以下是一個查詢MySQL服務版本號和當前數據:
針對上方的例子,我作如下闡釋:
一條查詢語句由一個SQL語句和緊隨其後的分號組成(不過有些例外情況,分號允許被省略。比如 QUIT 命令)。
當你觸發一條查詢語句,mysql將其發送到server並執行隨後展示出查詢結果,之後會打印出另一個 mysql> 提示,表示可以繼續輸入查詢語句了。
mysql查詢結果將以類似表格的形式展示(行與列)。第一行包含列的標籤,隨後的行即是查詢結果。通常的,列標籤為你查詢的數據庫表的字段的名字。
mysql展示了一共查詢了多少行,還有查詢時長。這些信息給你提升查詢語句的性能提供了建議。這些性能數據是不精確的,因為他們只是代表了這一過程的時間(不代表CPU或者機器時間),而這一過程的時長受服務加載和網絡延遲的因素影響。
鍵入的查詢語句是大小寫不敏感的,以下查詢語句是等價的。
mysql> SELECT VERSION(), CURRENT_DATE;mysql> select version(), current_date;mysql> SeLeCt vErSiOn(), current_DATE;
如下為另一個查詢語句,這示範了你可以使用mysql做簡單的計算:
到現在為止,所有的查詢語句都是簡短的、單行的語句。你可以在單行中鍵入多條查詢語句。只需要在每條語句後加上分號:
一條查詢語句不需要總是在單行上書寫,一個很長的查詢語句使得折行成為必要的需求。mysql會識別分號作為一條單獨的查詢語句,如果mysql沒有識別到分號則不會執行查詢語句。
以下為一個多行語句:
在這個例子中,注意提示信息是如何在你多行的第一行時從 mysql> 變成 -> 的,這個縮進表示一個沒有完成的語句,正在等待用戶的輸入。這個提示時你的朋友,因為它提供了可用的回調接口。如果你想使用這一回調,你需要知道mysql正在等待用戶輸入什麼。
如果你在未完成的語句鍵入完畢之前決定不想要執行了,鍵入 \c 取消這一語句。
下方表單列出了每一個你會在mysql看到的提示信息。
Prompt | Meaning |
---|---|
mysql> | Ready for new query |
-> | Waiting for next line of multiple-line query |
'> | Waiting for next line, waiting for completion of a string that began with a single quote (' ) |
"> | Waiting for next line, waiting for completion of a string that began with a double quote (" ) |
`> | Waiting for next line, waiting for completion of an identifier that began with a backtick (` ) |
/*> | Waiting for next line, waiting for completion of a comment that began with /* |
有些時候因為粗心忘記寫分號,而意外的產生了多行的情況,這是mysql會等待你的繼續輸入:
如果你也遇到了這種情況,可能是因為mysql正在等待你的分號。你只需要隨即輸入一個分號即可結束這條執行語句,並且mysql會開始執行這條語句:
'> 和 "> 提示經常由於字符集的文字而發生(換句話說,MySQL等待你完成一次字符串的輸入),在MySQL 中,你可以使用單引號和雙引號將字符串包裹起來(比如 'hello' 或者 "goodbye" ),並且mysql允許你跨越多行書寫一串字符串,當你看到 '> 和 "> 的提示信息時,這意味著你剛才輸入的哪一行指令中有以單引號或雙引號開頭的字符串,但是mysql沒有找到成對的作為結結束的單引號或雙引號。這只是因為你不小心造成的。
如果你鍵入查詢語句,然後回車等待MySQL的返回結果,發現什麼也沒有返回,你會想知道為什麼這次查詢耗費如此長的時間,此時你應該留意到 '> 這一提示,這表明mysql期望看到成對的單引號或者雙引號(你也遇到類似的問題了咩? 字符串 'Smith 缺少了 ' 來結束這個字符串)。
這是,你應該怎麼辦呢?最簡單的辦法就是結束本次查詢,然而,你不能像上邊介紹到的使用 \c ,因為mysql將 \c這一命令理解為仍然是字符串的一部分,正確的做法是,輸入閉合引號(這樣mysql就知道了你已經完成了字符串的輸入),緊接著再輸入 \c ,如此一來,便可以結束本次查詢:
這時,提示信息又變成了 mysql> ,這表示mysql已經準備好你輸入新的查詢語句了。
`> 提示信息和 '> 或 "> 提示很相似,注意區分。
區分 `> 和 '> 還有 "> 很重要,因為如果你因為沒有閉合引號而犯了錯誤,任何新的一行都會等待你輸入閉合引號,其他所有的特殊指令都會被認為是字符串的一部分而被忽略掉它原本的作用(比如輸入 QUIT 也會無效)。
3、創建和使用數據庫
學會了如何鍵入SQL語句,你準備好開始學習進入數據可了咩?
假設在你的家中(動物園)養了幾隻寵物,你希望將他們成長的過程中產生的各種各樣的信息作為足跡保存下來。你可以創建一個表格存放他們的數據,也可以當你想要獲取他們的信息的時候能隨時獲取。請跟隨以下步驟完成你的學習任務:
創建一個數據庫
創建一張表
將信息存入表中
用各種各樣的方法檢索表中的數據
使用多張表
這個動物園的數據庫創建起來很簡單(有意為之),但是也許在實際的動物園管理中創建類似的數據庫也不會太難。舉個栗子,一位農場主希望用數據庫記錄牲畜的各種信息,或者一名獸醫想要觀察記錄生病的動物的情況。
使用 SHOW 命令查找在當前服務中存在的所有數據庫:
mysql> SHOW DATABASES;+----------+| Database |+----------+| mysql || test || tmp |+----------+
名為 mysql 的數據庫記錄了用戶進入的權限。名為 text 的數據庫通常作為可使用的工作區或者開發者用來測試的地方。
列出數據庫的語句在你的機器上也許有所不同,如果你沒有權限使用 SHOW DATABASES 命令那麼這條語句不會返回任何內容。獲取幫助前往 Section 13.7.5.14, “SHOW DATABASES Syntax”.
如果 test 數據庫存在,嘗試進入該數據庫:
mysql> USE testDatabase changed
USE 命令和 QUIT 命令一樣,都不需要分號作為結尾。(當然你也可以在其後寫上分號,也不會有什麼危害)。 USE 是一個特殊的語句,它必須在單行上書寫。
你可以使用 test數據庫做以下的訓練,但是你創建的任何數據都有可能被能進入該數據庫的開發者刪除,所以你有必要詢問你的MySQL管理員,徵求一個屬於自己的數據庫,如果你想創建自己的 menagerie ,管理員需要執行類似以下的命令:
mysql> GRANT ALL ON menagerie.* TO 'your_mysql_name'@'your_client_host';
3.1、創建和選擇數據庫
如果管理員創建了僅有你可以使用的數據庫,你可以開始使用它。否則你需要親自創建:
在Unix系統之下,數據庫名稱是大小寫敏感的(SQL語句是不敏感的),所以你必須總是輸入 menagerie,而 Menageria和MENAGERIE或其他變量名均不可以。除了數據庫名,創建表名也要注意大小寫敏感這件事,因此請保持良好的命名習慣,注意區分大小寫。
創建一個數據庫而不改變為當前數據庫。你必須明確這件事,讓 menageria 變成當前數據庫,使用這個語句:
你的數據庫只需要創建一次,但是你必須在每次開始一次mysql會話之前先選擇一個數據庫。你可以使用 USE 語句轉換數據庫。或者你也可以在進入mysql的同時告訴mysql你想使用哪一個數據庫。只需要在連接參數後製定數據庫名稱。舉個例子:
shell> mysql -h host -u user -p menagerieEnter password: ********
3.2、創建一張表
創建數據庫是比較普通的部分,但是目前為止還是空空如也,不信可以 SHOW TABLES 語句:
最艱難的部分是決定數據庫的表結構應該是怎麼樣的:需要哪些表,這些表都有那些列標籤。
你想要創建一個記錄每一個寵物的表。所以這個表可以叫做 pet,至少需要包含每一個動物的名字。因為表中僅僅存在名字信息顯得太無趣,這張表還應當包含信息。舉個例子,如果你的家中有多個照顧寵物的人,那麼還需要記錄寵物的飼養人。你也許還想要記錄一些基礎的描述信息,比如物種和性別。
還有年齡的記錄呢?那樣事情就有趣多了,但是將他存放在數據庫中並不是很好,因為年齡會隨著時間的推移而發生變化,也就是說我們還去要經常的更新表中寵物的年齡的數據,因此如果能將動物的出生日期作為固定值保存下來會更好些。隨後,無論何時你需要寵物的年齡數據,你可以通過當前時間和寵物的出生日期計算出寵物的年齡,MySQL提供了操作日期的算法,所以實現它並不十分困難。保存出生日期而不保存年齡還有其他的優勢:
你可以使用數據庫來提醒你寵物的生日(也許你會覺得提醒動物的生日這件事有些愚蠢,但是別忘了,這只是一個例子,也許在其他使用場景中,你確實會需要數據庫來提醒公司裡大家的生日信息)。
你可以通過和當前日期作比較來計算年齡。舉個例子,如果你存儲了死亡日期在數據庫了,你可以很容易的計算出寵物去世時的年齡。
你也許還想在 pet 表中存入其他類型的信息。但是目前這些字段足夠了:name,owner,species,sex,birth和death。
使用 CREATE TABLE 語句去定製表的佈局:
VARCHAR 數據類型對與name,owner和species來說是最合適不過的了。因為這些字段的長度的不固定的可變的。這些字段的長度不是也不相同,也不能固定為20。你可以保存1到65535長度的長度的數據,這取決於你自己。如果你無法現在做出抉擇(抉擇數據的長度),你可以使用MySQL提供的 ALTER TABLE 語句來改變字段信息。
有幾種類型的值可以代表寵物的性別,比如說m和f,或者male和female。最簡單的是使用m和f來記錄寵物的性別。
death字段的數據類型毋庸置疑的為DATE。
一旦你創建一張表,SHOW TABLES 會輸出所有表:
為了能驗證你創建的表是期待的樣子,可以使用 DESCRIBE 語句:
你可以隨時使用 DESCRIBE 語句。舉個例子,如果你忘記了表中列的名字或者字段的數據類型你可以通過這種方法查看錶結構。
3.3、向表中添加數據
創建完一張表之後,你需要向其中添加數據,LOAD DATA 和 INSERT 語句是很實用的命令。
假設你的寵物記錄如下:
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 |
你可以創建一個叫做 pet.txt 的文本文件,這個文本文件包含一條寵物信息的記錄。使用製表符(TAB鍵)將值分隔開,值的順序就是CREATE TABLE 時字段的順序,如果要忽略某個值(比如不知道寵物的的性別或者去世日期),你可以使用NULL值,在文本文件中,使用\N (反斜槓加一個大寫的N),舉個例子,一直鳥的信息看起來就像這個樣子(空白處是一個TAG符):
Whistler Gwen bird \N 1997-12-09 \N
將文本文件的一條數據插入到pet表中,使用以下語句:
mysql> LOAD DATA LOCAL INFILE '/path/pet.txt' INTO TABLE pet;
如果你在window創建的文件,則是以 \r\n 作為一行的結束,你應該使用如下的語句:
mysql> LOAD DATA LOCAL INFILE '/path/pet.txt' INTO TABLE pet -> LINES TERMINATED BY '\r\n';
(在運行OS X系統的蘋果電腦中,你應該使用 LINES TERMINATED BY '\r')。
如果你想,你可以指定列值的分割符,明確指定 LOAD DATA 的結束標誌,但是默認的使用TAB符和換行符來分割。
如果遇到問題,獲取幫助前往Section 6.1.6, “Security Issues with LOAD DATA LOCAL”。
當你想要插入數據時, INSERT 語句是很實用的。
3.4、檢索數據
SELECT 語句通常用於從表中拉數據,通常的語句是:
SELECT what_to_selectFROM which_tableWHERE conditions_to_satisfy;
what_to_select 代表你想要查詢的字段,這可以是列標籤或者是 * 通配符(全部列)。which_table 代表你想要從那個表中獲取數據。WHERE 子句是可選的,如果出現了該子句,conditions_to_satisfy 表示一個或更多個檢索數據的條件。
選取所有的數據
這是最簡單的使用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 |+----------+--------+---------+------+------------+------------+
如果你想要瀏覽全部數據,是有此方法很實用,有時候你也許會覺得有些數據不準確,你發現正確的生日日期應該是1989而不是1979年。
這有至少兩種方法修正這一錯誤:
編輯 pet.txt 文件修正錯誤,然後清空該表,最後使用 DELETE 和 LOADDATA 重新導入數據。
mysql> DELETE FROM pet;mysql> LOAD DATA LOCAL INFILE '/path/pet.txt' INTO TABLE pet;
僅僅修復錯誤的記錄,你可以使用 UPDATE 語句。
mysql> UPDATE pet SET birth = '1989-08-31' WHERE name = 'Bowser';
選取特殊的行
正如上一張介紹的,檢索表的全部內容很容易。忽略了 SELECT 語句的 WHERE 子句。但是也許你不想要檢索到整張表的數據
mysql> SELECT * FROM pet WHERE name = 'Bowser';+--------+-------+---------+------+------------+------------+| name | owner | species | sex | birth | death |+--------+-------+---------+------+------------+------------+| Bowser | Diane | dog | m | 1989-08-31| 1995-07-29|+--------+-------+---------+------+------------+------------+
還可以選取一個範圍
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 擁有更高的優先級。如果你需要兩種操作符,使用括號運算符準確的包裹條件將其分組是一個不錯的選擇。
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 |+-------+--------+---------+------+------------+-------+
選取指定的列(字段)
如果你不想查詢表的全部行,而是隻關心感興趣的列,使用 逗號 將字段分隔開,舉個例子,如果你想要知道你的動物們是何時出生的,選擇 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(寵物的飼養員) 字段,你可以看到,這些飼養員出現多次,為了去除重複的查詢結果,壓縮查詢結果,只需要添加 DISTINCT 關鍵字便可以只出現一次。
mysql> SELECT DISTINCT owner FROM pet;+--------+| owner |+--------+| Benny || Diane || Gwen || Harold |+--------+
你還可使用 ** WHERE** 子句聯合行與列的查詢,舉個例子,只獲取 狗和貓 的出生日期、姓名和物種:
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 |+--------+---------+------------+
將查詢結果排序
將動物們的出生日期信息按日期排序:
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 |+----------+------------+
默認的排序為正向排序,也就是最小的值在前,為了使用逆向排序,只需添加 DESC 關鍵字:
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 |+----------+------------+
還可以按多個字段排序,如此一來,當第一個排序有重複,則會按第二個排序:
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 (逆向排序) 只對 birth字段起作用,對 species 仍使用正向排序。
計算日期
MySQL提供了一些計算日期的功能函數,舉個例子,計算年齡或者日期的額外部分。
為了確定你的寵物的年齡,使用 TIMESTAMPDIFF() 函數。該函數有三個參數,第一個為計算結果的單位,另外兩個參數為兩個日期。
mysql> SELECT name, birth, CURDATE(), -> TIMESTAMPDIFF(YEAR,birth,CURDATE()) 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 |+----------+------------+------------+------+
如果將查詢結果進行排序,將提升查詢結果的可讀性。如下,將按寵物名將查詢結果進行排序。
mysql> SELECT name, birth, CURDATE(), -> TIMESTAMPDIFF(YEAR,birth,CURDATE()) 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 |+----------+------------+------------+------+
如果想要將查詢結果按年齡排序,只需要將 name 替換成 age。
mysql> SELECT name, birth, CURDATE(), -> TIMESTAMPDIFF(YEAR,birth,CURDATE()) 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 |+----------+------------+------------+------+
如果想查詢已經去世的寵物的信息,只需要將死亡日期不為NULL的列表查詢出來即可。
mysql> SELECT name, birth, death, -> TIMESTAMPDIFF(YEAR,birth,death) AS age -> FROM pet WHERE death IS NOT NULL ORDER BY age;+--------+------------+------------+------+| name | birth | death | age |+--------+------------+------------+------+| Bowser |1989-08-31| 1995-07-29 | 5 |+--------+------------+------------+------+
細心的你也許已經注意到了,查詢去世日期使用的是 ISNOT NULL 而不是 <> NULL 因為 NULL是一個特殊的值,不能使用普通的操作符來比較 NULL。
如果你想要知道哪一個動物下一個月生日?MySQL提供了幾個函數處理日期。比如 YEAR(), MONTH() 和 DAYOFMONTH().MONTH() 。
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 |+----------+------------+--------------+
假設現在是四月,你想要查詢5月出生的動物:
mysql> SELECT name, birth FROM pet WHERE MONTH(birth) = 5;+-------+------------+| name | birth |+-------+------------+| Buffy | 1989-05-13|+-------+------------+
如果當前的月份是12月則會出現一個小小的麻煩,你不能單純的在12月加上1來獲取13月生日的動物。因為沒有13月,而是應該查詢1月生日的動物。
那如何才能不需要關心當前月份而獲取下一個月份的數字呢? DATE_ADD() 可以將你給定的月份的基礎上增加一個月,如果你使用CURDATE() 來獲取當前月份並加1:
mysql> SELECT name, birth FROM pet -> WHERE MONTH(birth) = MONTH(DATE_ADD(CURDATE(),INTERVAL 1 MONTH));
完成這項任務的另一種方法:
mysql> SELECT name, birth FROM pet -> WHERE MONTH(birth) = MOD(MONTH(CURDATE()), 12) + 1;
NULL值
NULL值是一個神奇的值,理論上講,NULL值是指a missing unknown value,NULL值和其他所有值都不相等。
為了測試NULL值的用法,使用 IS NULL 和 IS NOT NULL 操作符:
你不能使用像 = , < 或者 <> 的算數比較運算符。為了證明這一點,請看如下例子:
因為所有和NULL進行算數比較的結果還是NULL,你不可能獲取任何有意義的結果。
在MySQL中,0 和 NULL 意味著 false。
模式匹配
MySQL提供標準的SQL模式匹配,其基於正則表達式。
SQL模式匹配允許你使用 _ 匹配任何單個字符串,使用 % 匹配任意數字(包括0字符)。在MySQL中,SQL模式默認的不區分大小寫,在模式匹配的時候,使用 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 結尾的名稱的記錄:
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的另一種類型的模式匹配是借鑑了正則表達式。當你想要測試這種類型的模式時,使用 REGEXP 和 NOT REGEXP 操作符(或者RLIKE 和 NOT RLIKE,他們都是同意義的。)
下方的列表描述了一些繼承自正則表達式的字符:
. 匹配任意的單個字符。
[...] 表示匹配中括號中的任何字符。舉個例子,**[abc]**匹配a,b或者c。如果想要匹配一個字符範圍,使用破折號即可,比如 [a-z] 匹配任一字母,同理 [0-9] 匹配任一數字。
* 通配符匹配0次或多次,舉個例子, x* 匹配任意個數的的 x ,[0-9]匹配任意個數的任意數字。. 匹配任意個數的任何符號。
REGEXP 模式匹配如果能檢測到任何位置則匹配成功。(與 LIKE 不同的是,LIKE 只有整個字符串符合匹配要求才會成功。)
為了能匹配待匹配字符串的開頭或結尾,可是使用 ^ 匹配開始或 $ 匹配結束。
為了證明MYSQL擴展的正則表達式是如何起作用的,前面使用 LIKE 查詢出的結果這裡將使用 REGEXP 重寫:
為了找到所有 names 是以 b 開頭的 記錄,使用 ^ 來匹配 name 的開始:
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 |+--------+--------+---------+------+------------+------------+
如果你真的想要讓匹配度變得大小寫敏感,需要使用 BINARY 關鍵字來讓普通字符串變成二進制字符串。這次只匹配 name 以小寫的 b 開頭的記錄:
mysql> SELECT * FROM pet WHERE name REGEXP BINARY '^b';
找到所有 names 是以 fy 結尾的記錄,使用 $ 匹配所有 name:
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 |+----------+-------+---------+------+------------+------------+
如果你使用SQL模式,在正則表達式的兩邊加上通配符(表示匹配前後所有字符)是沒有必要的,因為正則表達式將會智能的從任何位置開始匹配待匹配字符串。
為了找到 names 僅僅包含5個字符的全部記錄,使用 ^ 和 $ 匹配 name 的開始和結束,然後將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} 來匹配 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 |+-------+--------+---------+------+------------+-------+
獲取更多關於正則表達式的幫助前往Section 12.5.2, “Regular Expressions”,這裡提供了關於正則表達式的更多信息。
查詢到了多少行記錄(計數)
數據庫經常需要回答類似這樣的問題,“某種確定類型的數據在表中存在多少個?”舉個例子,你也許想要知道你有多少寵物。或者每一位飼養員各有多少寵物。或者你想要對你的全部動物們進行各種各樣的普查。
獲得全部動物的總個數這個問題和“pet這個表中一共有多少條記錄?”的問題本質上相同。因為每一個動物對應一條記錄。COUNT(*) 函數能對所有行進行計數。因此查詢動物的個數的SQL語句就像這樣:
mysql> SELECT COUNT(*) FROM pet;+----------+| COUNT(*)|+----------+| 9 |+----------+
你也許想要查詢飼養員的名字。如果你想要查詢出每一個飼養員各飼養了多少個寵物,你可是使用 COUNT() 函數:
mysql> SELECT owner, COUNT(*) FROM pet GROUP BY owner;+--------+----------+| owner | COUNT(*) |+--------+----------+| Benny | 2 || Diane | 2 || Gwen | 3 || Harold | 2 |+--------+----------+
剛才的查詢中使用了 GROUP BY 將每一位 owner 的記錄分組。COUNT() 和 GROUP BY 搭配使用對於應付各種各樣描述分組的情況非常實用。下面的例子將以另一種方式對動物進行普查操作。
每一個物種的數量:
mysql> SELECT species, COUNT(*) FROM pet GROUP BY species;+---------+----------+| species | COUNT(*) |+---------+----------+| bird | 2 || cat | 2 || dog | 3 || hamster | 1 || snake | 1 |+---------+----------+
每一種性別的動物的數量:
mysql> SELECT sex, COUNT(*) FROM pet GROUP BY sex;+------+----------+| sex | COUNT(*) |+------+----------+| NULL | 1 || f | 4 || m | 4 |+------+----------+
(瀏覽上面的輸出結果,NULL代表性別未知。)
將性別和物種組合起來,查詢他們的數量:
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()**時,你不需要檢索出整個表。舉個例子,針對上一次查詢,僅僅查詢 狗狗 和 喵喵,就像這樣:
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 |+---------+------+----------+
或者,如果你想要知道每一種已知性別的動物的性別和物種的數量:
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 |+---------+------+----------+
如果你希望將選中列在某一條件下使用 COUNT() 進行計數,則 GROUP BY 子句必須必須出現前面出現過的字段名。否則,將會發生下面的情況:
如果 ONLY_FULL_GROUP_BY SQL模式是激活狀態,則會報一個錯誤:
mysql> SET sql_mode = 'ONLY_FULL_GROUP_BY';Query OK, 0 rows affected (0.00 sec)mysql> SELECT owner, COUNT(*) FROM pet;ERROR 1140 (42000): In aggregated query without GROUP BY, expression#1 of SELECT list contains nonaggregated column 'menagerie.pet.owner';this is incompatible with sql_mode=only_full_group_by
如果 ONLY_FULL_GROUP_BY 是未被激活狀態,則mysql對查詢語句的處理方式會將全部行看作一個單一的組,但是不能確定更詳盡的計數信息。
mysql> SET sql_mode = '';Query OK, 0 rows affected (0.00 sec)mysql> SELECT owner, COUNT(*) FROM pet;+--------+----------+| owner | COUNT(*) |+--------+----------+| Harold | 8 |+--------+----------+1 row in set (0.00 sec)
獲取更多關於 GROUP BY的處理行為 的幫助前往 Section 12.19.3, “MySQL Handling of GROUP BY”.;
訪問Section 12.19.1, “Aggregate (GROUP BY) Function Descriptions” ,獲取更多關於 COUNT(expr) 行為的最優優化方式的幫助。
使用更多的表
pet 表記錄了你擁有的全部寵物,如果你想要記錄關於他們的其他信息,比如他們看獸醫或者生小寶寶的歷史性事件信息。你需要另外的一個表,那麼這個表應該是什麼樣子的呢?他至少應當包含如下信息:
寵物姓名,這樣你才能知道這些事件屬於哪一個動物的。
日期,你可以知道這些事件發生的時間。
還需要一個字段詳細描述這一事件。
還需要事件類型的字段,如果你想要將事件進行分類的話。
有了以上的考量,使用 CREATE TABLE 語句創建 event 表,它看起來就像這樣:
mysql> CREATE TABLE event (name VARCHAR(20), date DATE, -> type VARCHAR(15), remark VARCHAR(255));
和之前的 pet 表類似,使用包含所有記錄的文本文件來初始化填充新創建的表是很容易的。這些信息看起來就像這樣。
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;
基於你之前創建 pet表的時候習得的知識,你可能需要檢索在 *event 表中的記錄,原理都是一樣的。但是你也許想知道創建這樣一個表何時才會用到?
假設你想要查詢每一個生過小寶寶的寵物的小寶寶出生起他的年齡。我們早前知道了如何通過兩個日期計算年齡,媽媽降生小寶寶時的日期存放在 event 表中,我們還需要知道媽媽的出生日期,便可以知道降生小寶寶時媽媽的年齡了,這一生日數據存在 pet 表中,也就是說我們需要兩個表的數據:
mysql> SELECT pet.name, -> TIMESTAMPDIFF(YEAR,birth,date) AS age, -> remark -> FROM pet INNER JOIN event -> ON pet.name = event.name -> WHERE 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 |+--------+------+-----------------------------+
有幾點需要注意的查詢事項:
FORM 子句將兩個表聯合起來,因為需要同時從兩個表中拉取數據。
當從多個表中聯合數據,你需要指明兩個表中的記錄如何一一對應。這很容易,因為他們都有 name 字段。這個查詢使用 ON 子句,使得兩個表中都存在 name 字段的記錄很容易一一對應。查詢語句中還是用了 INNER JOIN 來聯合兩個表,這一關鍵字表示當且僅當兩個表中同時滿足包含 name 字段時,這一條記錄才符合條件。在這個例子中, ON 子句指明 name 字段同時存在於 pet 表和 event 表中。如果 name 字段僅僅出現在一個表中而沒有出現在另一個表中,則這一條將不會出現在查詢結果當中,因為不滿足 ON 子句的條件。
因為 name 字段同時存在於兩個表中,因此當你使用 name 字段值的時候你必須指明是哪一個表中的 name 字段值。比如是 pet.name還是 event.name。
你不需要將兩個完全不相同的表聯合起來。有些時候一個表聯合他自己是很實用的,如果你想要比較一張表中的一組條記錄和另一組記錄。舉個例子,你想要查詢 pet 表中一對可以繁殖下一代的寵物,你可以通過如下方法產生出一個雌性與雄性的候選:
mysql> SELECT p1.name, p1.sex, p2.name, p2.sex, p1.species -> FROM pet AS p1 INNER JOIN pet AS p2 -> ON 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 |+--------+------+--------+------+---------+
在這次查詢中,我們給表的名字定義了兩個別名分別為 p1 和 p2。
4、獲取數據庫和表的信息
一旦你忘記了數據庫或者表的名字,或者表的結構(舉個例子,字段的全稱怎麼拼?),MySQL為我們解決了這些問題,他提供了幾個數據庫和表支持的很實用的語句來幫助我們。
在前幾章裡,你學會了使用 SHOW DATABASES 顯示全部數據庫的列表。那麼如何找到當前正在使用哪一個數據庫呢?使用 DATABASES()函數:
mysql> SELECT DATABASE();+------------+| DATABASE() |+------------+| menagerie |+------------+
如果你沒有選擇任何數據庫,則上方的查詢結果為NULL。
為了查詢出當前數據庫包含那些表(舉個例子,當你不是很確定表的名字怎麼拼寫的時候。)。使用如下語句:
mysql> SHOW TABLES;+---------------------+| Tables_in_menagerie |+---------------------+| event || pet |+---------------------+
返回的查詢結果的字段名總是 Tables_in_db_name ,其中 db_name 就是你的數據庫的名字,獲取更多幫助信息訪問 Section 13.7.5.37, “SHOW TABLES Syntax”。
如果你想要查詢表的結構,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列是數據類型,NULL表示該字段可以包含NULL,key 表示當前字段是否為整張表的索引,Default 指明當前字段如果在插入數據時不填則使用什麼默認值。Extra 顯示了每一個字段的額外信息:如果這一字段需要自增 AUTO_INCREMENT ,那麼會填入Extra 中。
DESC 是 DESCRIBE 的簡寫形式,獲取幫助請前往 Section 13.8.1, “DESCRIBE Syntax”。
你可以獲得已經存在的一張使用 CREATE TABLE 語句創建的表在創建時所必須的關鍵字,可是使用 SHOW CREATE TABLE 語句來獲得。關於該命令的更多幫助信息前往Section 13.7.5.10, “SHOW CREATE TABLE Syntax”.。
如果你在一張表中建立了索引,SHOW INDEX FROM tbl_name,獲取更多幫助信息前往 Section 13.7.5.22, “SHOW INDEX Syntax”。
5、使用mysql的批處理模式
在前面的章節,你使用mysql交互式輸入語句和瀏覽查詢結果。你也可以在批處理模式中執行mysql。為了達到這一目的,將你希望執行的語句寫入文件中,並告訴msql讀取該文件,將文件內容輸入到此處。
shell> mysql < batch-file
如果你在Windows平臺下編寫文件,那麼文件中將會出現一些奇怪的字符,你可以這樣做:
C:\> mysql -e "source batch-file"
當你以這種方法使用mysql時,你也就創建了一個相當於腳本文件的東西,然後執行這個腳本。
如果你想要在腳本拋出錯誤時仍然繼續執行,你應當使用 --force 命令行參數。
使用腳本的優勢有哪些?有以下幾點:
如果你需要執行重複的查詢任務(比如說,每天或者每週都要執行重複的任務),將他做成一個腳本你就不再需要每次執行他的時候還要再輸入一次。
你可以通過拷貝(或者稍加修改)的方式直接從現存的查詢語句生成一個新的查詢語句。
批處理模式對很長的多行查詢語句非常有幫助。如果你犯了錯誤,你不在需要重新在命令行從頭寫一遍,只需要編輯你的腳本將錯誤的位置變成正確的,然後告訴mysql在一次執行他即可。
如果你有一個會輸出很多結果的查詢,你可以通過翻頁的形式翻閱查詢結果,而不是讓查詢結果一下子滾動到屏幕的頂端。
shell> mysql < batch-file | more
你可以貢獻你的腳本給別人,如此以來別人也可以執行你寫的查詢語句。
一些情況不允許使用交互式輸入,舉個例子,當你需要定時的執行查詢語句,你就必須讓機器自動的執行批處理腳本。
當你在批處理模式和交互式輸入模式執行mysql語句是。兩者默認的輸出格式是不相同的(顯而易見)。舉個例子,我們執行並輸出 SELECT DISTINCT species FROM pet 看起來像這樣:
+---------+| species |+---------+| bird || cat || dog || hamster || snake |+---------+
批處理模式中,輸出內容看起來像這樣:
speciesbirdcatdoghamstersnake
如果你想要在批處理模式中得到像交互式模式的格式,使用 mysql -t ,輸出執行的腳本文件,使用 mysql -v。
你也可以通過mysql的提示符來使用腳本,例如:
mysql> source filename;mysql> \. filename
獲取更多幫助信息前往Section 4.5.1.5, “Executing SQL Statements from a Text File”。
6、命令行查詢示例
以下是解決一些MYSQL命令問題的示例。
一些示例使用 shop 這張表,每一個售貨員銷售的每一件商品(條目數量)的價格。假設每一個售貨員對每一件商品都有固定的交易價格,並且(商品,售貨員)是記錄的主鍵。
打開命令行工具mysql,並且選擇一個數據庫:
shell> mysql your-database-name
(在一些MYSQL的安裝環境中,你可以使用叫做 test 的數據庫)。
你可是使用如下語句創建一張表:
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));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);
在開始探討上面語句之前,整張表應該包含如下的內容:
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 |+---------+--------+-------+
一組數據中的最大值
“最大值是多少?”
SELECT MAX(article) AS article FROM shop;+---------+| article |+---------+| 4 |+---------+
擁有最大值的整條記錄
任務:查詢出最貴的商品的數兩,交易額和價格。
使用子查詢是很容易辦到的:
SELECT article, dealer, priceFROM shopWHERE price=(SELECT MAX(price) FROM shop);+---------+--------+-------+| article | dealer | price |+---------+--------+-------+| 0004 | D | 19.95 |+---------+--------+-------+
另一種結局辦法是使用 LEFT JOIN 或者 將所有的記錄根據價格逆向排序然後得到第一條記錄,其中使用到了MYSQL指明條件的 LIMIT 子句。
SELECT s1.article, s1.dealer, s1.priceFROM shop s1LEFT JOIN shop s2 ON s1.price < s2.priceWHERE s2.article IS NULL;SELECT article, dealer, priceFROM shopORDER BY price DESCLIMIT 1;
注意:如果這裡有 幾件 最貴的商品,每一件商品價值19.95,那麼 LIMIT 解決方案僅僅能獲取其中 一 件。
每一組商品的最大值
任務:查詢出每一件商品的最大值
SELECT article, MAX(price) AS priceFROM shopGROUP BY article;+---------+-------+| article | price |+---------+-------+| 0001 | 3.99 || 0002 | 10.99 || 0003 | 1.69 || 0004 | 19.95 |+---------+-------+
寫在最後:
上次翻譯完socket.io的官方文檔,這次翻譯mysql的官方參考手冊,感觸最深的是:國外的文檔會把每一個知識點用最最最生動形象的例子和容易被人理解方式的從各種角度反反覆覆的講了一遍又一遍(小孩子都能聽懂了!甚至稍微有些囉嗦,),目的是力求學生真的學會了搞懂了。國內的有些教程則喜歡把原本挺簡單的東西給複雜化。
轉:https://www.shuaihua.cc/article/1505472284172/
1、具有1-5工作經驗的,面對目前流行的技術不知從何下手,
需要突破技術瓶頸的。2、在公司待久了,過得很安逸,
但跳槽時面試碰壁。需要在短時間內進修、跳槽拿高薪的。
3、如果沒有工作經驗,但基礎非常紮實,對java工作機制,
常用設計思想,常用java開發框架掌握熟練的。
4、覺得自己很牛B,一般需求都能搞定。
但是所學的知識點沒有系統化,很難在技術領域繼續突破的。
5. 群號:高級架構群 606187239備註好信息!
6.阿里Java高級大牛直播講解知識點,分享知識,
多年工作經驗的梳理和總結,帶著大家全面、
科學地建立自己的技術體系和技術認知!