MySQL必知必會—概念篇mysql
# 檢索單個列,例如從 products 表中檢索一個名爲 prod_name 的列。 SELECT prod_name FROM products; # 檢索多個列。注意,列名之間要用逗號分隔,最後一個列名後不要加逗號,會報錯。 SELECT prod_id, prod_name, prod_price FROM products; # 檢索全部列。 SELECT * FROM products; # 只檢索出不一樣的行, DESTINCT 關鍵字可讓指令只返回不一樣的值。若是指令,products 表中可能一共有14行,如今只返回不一樣(惟一)的 vend_id 行,可能就只返回4行了。 SELECT DISTINCT vend_id FROM products; # 限制結果, LIMIT 5 表示只返回很少於5行。 SELECT prod_name FROM products LIMIT 5; # LIMIT 5, 5 表示返回從行5開始的5行。 SELECT prod_name FROM products LIMIT 5, 5; # 或者使用 LIMIT 5 OFFSET 5, 跟上面結果相同。 SELECT prod_name FROM products LIMIT 5 OFFSET 5; # 注意,返回行數是從 0 開始的。因此,LIMIT 1, 1 將檢索出第二行,而不是第一行。 SELECT prod_name FROM products LIMIT 1,1;
不使用排序時,其實檢索出的數據並非以純粹的隨機順序顯示的,數據通常將以它在底層表中出現的順序顯示。這能夠是數據最初添加到表中的順序,可是,若是數據後來進行過更新或者刪除,則此順序將會受到 MySQL 重用回收存儲空間的影響。所以,若是不明確控制的話,不能(也不該該)依賴該排序順序。github
關係數據庫設計理論認爲:若是不明確規定排序順序,則不該該假定檢索出的數據的順序有意義。正則表達式
ORDER BY 子句,能夠給 SELECT 語句檢索出來的數據進行排序。 ORDER BY 子句取一個或多個列的名字。據此對輸出進行排序。算法
# 沒有排序 SELECT prod_name FROM products; # 對 prod_name 列以字母順序排序數據 SELECT prod_name FROM products ORDER BY prod_name; # 按多個列排序:以下會先按照 prod_price 排序, # 只有出現相同的 prod_price 時,纔會再按照 prod_name 排序。 SELECT prod_id, prod_price, prod_name FROM products ORDER BY prod_price, prod_name; # 指定排序方向,默認是升序,例如按照 prod_price 降序排序(最貴的排在最前面) SELECT prod_id, prod_price, prod_name FROM products ORDER BY prod_price DESC; # 多個列排序,例如按照 prod_price 降序,最貴的在最前面,而後在對產品名排序 SELECT prod_id, prod_price, prod_name FROM products ORDER BY prod_price DESC, prod_name; # ORDER BY 和 LIMIT 搭配,能夠找出一個列中最高或最低的值。 SELECT prod_price FROM products ORDER BY prod_price DESC LIMIT 1;
數據庫包含大量的數據,可是咱們不多須要檢索表中全部的行。只檢索所需數據須要指定過濾條件,在 SELECT 語句中,數據根據 WHERE 子句中指定的搜索條件進行過濾。sql
# 檢索 pro_price 爲 2.50 的行 SELECT prod_name FROM products WHERE prod_price = 2.50; # 執行篩選匹配時默認不區分大小寫,因此 fuses 能夠檢索出 Fuses SELECT prod_name, prod_price FROM products WHERE prod_name = 'fuses'; # 輸出 +-----------+------------+ | prod_name | prod_price | +-----------+------------+ | Fuses | 3.42 | +-----------+------------+ # 檢索出 vend_id 不等於 1003 的行 SELECT vend_id, prod_name FROM products WHERE vend_id <> 1003; # 檢索 prod_price 在 5 到 10 之間的全部行 SELECT prod_name, prod_price FROM products WHERE prod_price BETWEEN 5 AND 10; # 檢查具備 NULL 值的列,用 IS NULL 子句 SELECT cust_id FROM customers WHERE cust_email IS NULL;
操做符 | 說明 |
---|---|
= | 等於 |
<> | 不等於 |
!= | 不等於 |
< | 小於 |
<= | 小於等於 |
> | 大於 |
>= | 大於等於 |
BETWEEN | 在指定的兩個值之間 |
MySQL 容許組合多個 WHERE 子句。這些子句分爲兩種方式使用:以 AND 子句的方式或 OR 子句的方式使用。數據庫
### AND 操做符 # 檢索出 vend_id 等於 1003 而且 prod_price 小於等於 10 的行 SELECT prod_price, prod_name FROM products WHERE vend_id = 1003 AND prod_price <= 10; #### OR 操做符 # 檢索出 vend_id 等於 1002 或 vend_id 等於 1003 的全部行 SELECT prod_name, prod_price FROM products WHERE vend_id = 1002 OR vend_id = 1003; # AND 和 OR 合用,AND 優先級高。 # 下面檢索出的結果是 vend_id 是 1003 而且 prod_price 大於等於 10 的和全部 vend_id 是 1002 的行。 SELECT vend_id, prod_name, prod_price FROM products WHERE vend_id = 1002 OR vend_id = 1003 AND prod_price >= 10; # 輸出結果 +---------+----------------+------------+ | vend_id | prod_name | prod_price | +---------+----------------+------------+ | 1002 | Fuses | 3.42 | | 1002 | Oil can | 8.99 | | 1003 | Detonator | 13.00 | | 1003 | Bird seed | 10.00 | | 1003 | Safe | 50.00 | | 1003 | TNT (5 sticks) | 10.00 | +---------+----------------+------------+ # 若是想檢索出 vend_id 是 1003 而且 prod_price 大於等於 10 的和 vend_id 是 1002 而且 prod_price 大於等於 10 的行,須要加括號。 SELECT vend_id, prod_name, prod_price FROM products WHERE (vend_id = 1002 OR vend_id = 1003) AND prod_price >= 10; ### IN 操做符,指定條件範圍,範圍中的每一個條件均可以進行匹配。IN 取值是所有括在圓括號中的由逗號分隔的列表。 SELECT vend_id, prod_name, prod_price FROM products WHERE vend_id IN (1002, 1003); ### NOT 操做符,否認它以後的任何條件 SELECT vend_id, prod_name, prod_price FROM products WHERE vend_id NOT IN (1002, 1003);
IN 和 OR 具備相同的功能,可是 IN 操做符有如下優勢segmentfault
%
表示任何字符出現任意次數,可使0次,1次,n次數組
### 找出全部以 jet 開頭的產品 SELECT prod_id, prod_name FROM products WHERE prod_name LIKE 'jet%'; +---------+--------------+ | prod_id | prod_name | +---------+--------------+ | JP1000 | JetPack 1000 | | JP2000 | JetPack 2000 | +---------+--------------+ ### 通配符可在搜索模式中任意位置使用,而且可使用多個通配符。 SELECT prod_id, prod_name FROM products WHERE prod_name LIKE '%anvil%'; +---------+--------------+ | prod_id | prod_name | +---------+--------------+ | ANV01 | .5 ton anvil | | ANV02 | 1 ton anvil | | ANV03 | 2 ton anvil | +---------+--------------+
下劃線 _ 只能匹配單個字符,只能匹配一個,不能多也不能少。數據庫設計
### 對比一下下面兩個通配符結果 SELECT prod_id, prod_name FROM products WHERE prod_name LIKE '_ ton anvil'; +---------+-------------+ | prod_id | prod_name | +---------+-------------+ | ANV02 | 1 ton anvil | | ANV03 | 2 ton anvil | +---------+-------------+ SELECT prod_id, prod_name FROM products WHERE prod_name LIKE '% ton anvil'; +---------+--------------+ | prod_id | prod_name | +---------+--------------+ | ANV01 | .5 ton anvil | | ANV02 | 1 ton anvil | | ANV03 | 2 ton anvil | +---------+--------------+ ### 下劃線通配符比百分號通配符少了一個 .5 的數據
### 基本字符匹配,下面的語句檢索列 prod_name 包含文本 1000 的全部行。 SELECT prod_name FROM products WHERE prod_name REGEXP '1000' ORDER BY prod_name; ### 區分大小寫須要用到 BINARY 關鍵字 SELECT prod_name FROM products WHERE prod_name REGEXP BINARY 'S'; ### 使用 | 進行 OR 匹配,能夠有兩個以上的 OR 條件,例如: '1000|2000|3000' SELECT prod_name FROM products WHERE prod_name REGEXP '1000|2000'; +--------------+ | prod_name | +--------------+ | JetPack 1000 | | JetPack 2000 | +--------------+ ### 匹配幾個字符之一 SELECT prod_name FROM products WHERE prod_name REGEXP '[1,2,3] Ton' ORDER BY prod_name; +-------------+ | prod_name | +-------------+ | 1 ton anvil | | 2 ton anvil | +-------------+ ### 注意區別 1|2|3 Ton,這表示匹配出 1,2和3 Ton,其實[123]是[1|2|3]的縮寫 SELECT prod_name FROM products WHERE prod_name REGEXP '1|2|3 Ton' ORDER BY prod_name; +---------------+ | prod_name | +---------------+ | 1 ton anvil | | 2 ton anvil | | JetPack 1000 | | JetPack 2000 | | TNT (1 stick) | +---------------+ ### 匹配特殊字符, \\ 來轉義特殊字符 SELECT vend_name FROM vendors WHERE vend_name REGEXP '\\.' ORDER BY vend_name; +--------------+ | vend_name | +--------------+ | Furball Inc. | +--------------+ ### 匹配出連在一塊兒的4個數字 SELECT prod_name FROM products WHERE prod_name REGEXP '[:digit:]{4}' ORDER BY prod_name; +--------------+ | prod_name | +--------------+ | JetPack 1000 | | JetPack 2000 | +--------------+
元字符 | 說明 |
---|---|
\f | 換頁 |
\n | 換行 |
\r | 回車 |
\t | 製表 |
\v | 縱向製表 |
\\ | 反斜槓 |
^ | 文本的開始 |
$ | 文本的結束 |
[[:<:]](8版本以後改成 b) | 詞的開始 |
[[:>:]](8版本以後改成 b) | 詞的結束 |
多數正則表達式實現使用單個反斜槓轉義特殊字符,以便能使用這些字符自己。但 MySQL 要求兩個反斜槓(MySQL本身解釋一個,正則表達式庫解釋另外一個)。
類 | 說明 |
---|---|
[:alnum:] | 任意字符和數字(同 [a-zA-Z0-9]) |
[:alpha:] | 任意字符(同 [a-zA-Z]) |
[:blank:] | 空格和製表 (同 [\t]) |
[:cntrl:] | ASCII控制字符 (ASCII 0 到 31 和 127) |
[:digit:] | 任意數字 (同 [0-9]) |
[:xdigit:] | 任意十六進制數字(同 [a-fA-F0-9]) |
[:lower:] | 任意小寫字母 (同 [a-z]) |
[:upper:] | 任意大寫字母(同 [A-Z]) |
[:print:] | 任意可打印字符 |
[:graph:] | 與[:print:]相同,但不包含空格 |
[:punct:] | 既不在[:alnum:]又不在[:cntrl:]中的任意字符 |
[:space:] | 包括空格在內的任意空白字符(同 [\f\n\r\t\v]) |
在不使用數據庫表的狀況下用 SELECT 來測試正則表達式。 REGEXP 檢查老是返回0(沒有匹配)或 1(匹配)。
SELECT 'hello' REGEXP 'hello\\b'; +---------------------------+ | 'hello' REGEXP 'hello\\b' | +---------------------------+ | 1 | +---------------------------+
### 將查出來的名字和國家拼接出來展現,使用了 Concat、Trim函數,和 AS 關鍵字 SELECT Concat( Trim(vend_name), '(', Trim(vend_country), ')') AS vend_name FROM vendors ORDER BY vend_name; +------------------------+ | vend_name | +------------------------+ | ACME(USA) | | Anvils R Us(USA) | | Furball Inc.(USA) | | Jet Set(England) | | Jouets Et Ours(France) | | LT Supplies(USA) | +------------------------+ ### 將20005訂單中的全部物品查出來,經過數量和單價算出總價 SELECT prod_id, quantity, item_price, quantity*item_price AS expanded_price FROM orderitems WHERE order_num = 20005; +---------+----------+------------+----------------+ | prod_id | quantity | item_price | expanded_price | +---------+----------+------------+----------------+ | ANV01 | 10 | 5.99 | 59.90 | | ANV02 | 3 | 9.99 | 29.97 | | TNT2 | 5 | 10.00 | 50.00 | | FB | 1 | 10.00 | 10.00 | +---------+----------+------------+----------------+
SELECT 提供了測試和實驗函數與計算的一個很好的方法,就是省略 FROM 子句
SELECT 3*2; +-----+ | 3*2 | +-----+ | 6 | +-----+ SELECT Now(); +---------------------+ | Now() | +---------------------+ | 2019-11-21 22:51:13 | +---------------------+
函數沒有 SQL 的可移植性強,幾乎每種主要的 DBMS 的實現都支持其餘實現不支持的函數,有時差別還很大。爲了代碼的可移植性,不少人不同意使用特殊實現的功能,雖然這樣作頗有好處,可是對於應用程序的性能可能出現影響。若是決定使用函數,應該保證作好代碼註釋。
函 數 | 說 明 |
---|---|
Left() | 返回串左邊的字符 |
Length() | 返回串的長度 |
Locate() | 找出串的一個子串 |
Lower() | 將串轉換爲小寫 |
LTrim() | 去掉串左邊的空格 |
Right() | 返回串右邊的字符 |
RTrim() | 去掉串右邊的空格 |
Soundex() | 返回串的 SOUNDEX 值 |
SubString() | 返回子串的字符 |
Upper() | 將串轉換爲大寫 |
SOUNDEX 是一個將任何文本串轉換爲描述其語音表示的字母數字模式的算法。SOUNDEX 考慮了相似的發音字節和音節,使得能對串進行發音比較而不是字母比較。
### 例如用 Y. Lie 把 Y Lee 搜出來,由於它們發音相似 SELECT cust_name, cust_contact FROM customers WHERE Soundex(cust_contact) = Soundex('Y. Lie'); +-------------+--------------+ | cust_name | cust_contact | +-------------+--------------+ | Coyote Inc. | Y Lee | +-------------+--------------+
函 數 | 說 明 |
---|---|
AddDate() | 增長一個日期(天、周等) |
AddTime() | 增長一個時間(時、分等) |
CurDate() | 返回當前日期 |
CurTime() | 返回當前時間 |
Date() | 返回日期時間的日期部分 |
DateDiff() | 計算兩個日期之差 |
Date_Add() | 高度靈活的日期運算函數 |
Date_Format() | 返回一個格式化的日期或時間串 |
Year() | 返回一個日期的年份部分 |
Month() | 返回一個日期的月份部分 |
Day() | 返回一個日期的天數部分 |
DayOfWeek() | 對於一個日期,返回對應的星期幾 |
Hour() | 返回一個時間的小時部分 |
Minute() | 返回一個時間的分鐘部分 |
Second() | 返回一個時間的秒部分 |
Now() | 返回當前日期和時間 |
### 檢索出日期爲 2005-09-01 這天的訂單記錄 SELECT cust_id, order_num FROM orders WHERE order_date = '2005-09-01'; ### 上面的檢索有個問題,若是 order_date 存儲的帶有時間,例如 2005-09-01 11:30:05 ,就檢索不到了,解決辦法是讓僅將給出的日期與列中的日期部分進行比較 SELECT cust_id, order_num FROM orders WHERE Date(order_date) = '2005-09-01'; ### 若是想檢索出2005年9月的全部訂單 ### 方法一,得記住每月有多少天,甚至要知道是否是閏年的2月 SELECT cust_id, order_num FROM orders WHERE Date(order_date) BETWEEN '2005-09-01' AND '2005-09-30'; ### 方法二, 使用 Year() 和 Month() 函數 SELECT cust_id, order_num FROM orders WHERE Year(order_date) = 2005 AND Month(order_date) = 9;
函 數 | 說 明 |
---|---|
Abs() | 返回一個數的絕對值 |
Sin() | 返回一個角度的正弦 |
Cos() | 返回一個角度的餘弦 |
Tan() | 返回一個角度的正切 |
Exp() | 返回一個數的指數值 |
Mod() | 返回除操做的餘數 |
Pi() | 返回圓周率 |
Rand() | 返回一個隨機數 |
Sqrt() | 返回一個數的平方根 |
函 數 | 說 明 |
---|---|
AVG() | 返回某列的平均值 |
COUNT() | 返回某列的行數 |
MAX() | 返回某列的最大值 |
MIN() | 返回某列的最小值 |
SUM() | 返回某列值之和 |
### 計算出 products 表中全部產品的平均價格 SELECT AVG(prod_price) AS avg_price FROM products; +-----------+ | avg_price | +-----------+ | 16.133571 | +-----------+ ### 查看 customers 表中全部客戶的總數 SELECT COUNT(*) AS num_cust FROM customers; +----------+ | num_cust | +----------+ | 5 | +----------+ ### 只對具備電子郵件地址的客戶計數 SELECT COUNT(cust_email) AS num_cust FROM customers; +----------+ | num_cust | +----------+ | 3 | +----------+ ### 計算出訂單號爲 20005 的物品總數 SELECT SUM(quantity) AS items_ordered FROM orderitems WHERE order_num = 20005; +---------------+ | items_ordered | +---------------+ | 19 | +---------------+ ### 多個彙集函數組合 SELECT COUNT(*) AS num_items, MIN(prod_price) AS price_min, MAX(prod_price) AS price_max, AVG(prod_price) AS price_avg FROM products; +-----------+-----------+-----------+-----------+ | num_items | price_min | price_max | price_avg | +-----------+-----------+-----------+-----------+ | 14 | 2.50 | 55.00 | 16.133571 | +-----------+-----------+-----------+-----------+
使用 DISTINCT 參數時,只會計算包含不一樣的值的行,若是指定參數爲 ALL 或者不指定參數,默認參數爲 ALL ,會計算全部的行。
### 看一下產品表裏有多少家供應商,由於有可能一家供應商提供不少產品。 ### 所有的行 SELECT COUNT(vend_id) AS vend_count FROM products; +------------+ | vend_count | +------------+ | 14 | +------------+ ### 去重後就知道有 4 家供應商 SELECT COUNT(DISTINCT vend_id) AS vend_count FROM products; +------------+ | vend_count | +------------+ | 4 | +------------+
() 會返回第一行)。
SELECT vend_id, prod_price FROM products GROUP BY vend_id, prod_price;
### 列出至少有兩個訂單的全部顧客 SELECT cust_id, COUNT(*) AS orders FROM orders GROUP BY cust_id HAVING COUNT(*) >= 2; ### 列出具備2個(含)以上、價格爲10(含)以上的產品的供應商 SELECT vend_id, COUNT(*) AS num_prods FROM products WHERE prod_price >= 10 GROUP BY vend_id HAVING COUNT(*) >= 2; ### 列出總計訂單價格大於等於50的訂單,並按照總價排序 SELECT order_num, SUM(quantity*item_price) AS ordertotal FROM orderitems GROUP BY order_num HAVING SUM(quantity*item_price) >= 50 ORDER BY ordertotal; +-----------+------------+ | order_num | ordertotal | +-----------+------------+ | 20006 | 55.00 | | 20008 | 125.00 | | 20005 | 149.87 | | 20007 | 1000.00 | +-----------+------------+
SELECT > FROM > WHERE > GROUP BY > HAVING > ORDER BY > LIMIT
一個持續更新的github筆記,連接地址:Front-End-Basics,能夠watch,也能夠star。
此篇文章的地址:MySql必知必會