Mysql 必知必會(huì)
查詢
-
檢索多個(gè)列
SELECT prod_id, prod_name, prod_price FROM Products;
注意歌亲,多個(gè)字段名稱之間要用
,
分割唤殴,最后一個(gè)字段不需要,
-
關(guān)于通配符 * 號(hào)
一般而言率挣,除非你確實(shí)需要表中的每一列枣接,否則最好別使用 * 通配符盒至。雖然使用通配符能讓你自己省事,不用明確列出所需列争舞,但檢索不需 要的列通常會(huì)降低檢索和應(yīng)用程序的性能凛忿。
-
DISTINCT 關(guān)鍵字
SELECT DISTINCT vend_id FROM Products;
對(duì)取到的結(jié)果里面
vend_id
去重SELECT DISTINCT vend_id, prod_name FROM Products;
去重,告訴DBMS只返回不同值竞川,如果使用 DISTINCT 關(guān)鍵字店溢,它必須直接放在列名的前面。
DISTINCT 關(guān)鍵字作用于所有的列委乌,不僅僅是跟在其后的那一列床牧。例如,你指定SELECT DISTINCT vend_id, prod_price
遭贸,除非指定的兩列完全相同戈咳,否則所有的行都會(huì)被檢索出來。 -
LIMIT
SELECT prod_name FROM Products LIMIT 5;
只取5行數(shù)據(jù)
SELECT prod_name FROM Products LIMIT 5 OFFSET 1;
取5行數(shù)據(jù)壕吹,從第一行開始(注意:數(shù)據(jù)庫是從0開始計(jì)數(shù)行的)
SELECT prod_name FROM Products LIMIT 5, 1;
前一個(gè)數(shù)字代表從第幾行開始著蛙,后一個(gè)數(shù)字代表取幾個(gè)數(shù)據(jù)
-
注釋
一共有三種類型
/** 注釋 */ -- 注釋 # 注釋
-
ORDER BY
- 按單個(gè)列排序
- 按多個(gè)列排序
- 按照列位置排序
ORDER BY子句的位置
在指定一條ORDER BY子句時(shí),應(yīng)該保證它是SELECT語句中最后一條子句耳贬。如果它不是最后的子句册踩,將會(huì)出現(xiàn)錯(cuò)誤消息。通過非選擇列進(jìn)行排序
通常效拭,ORDER BY子句中使用的列 SELECT 選擇的列。但是胖秒,實(shí)際上并不一定要這樣缎患,用其他列也是完全合法的SELECT prod_id, prod_price, prod_name FROM Products ORDER BY prod_price, prod_name;
先按照 prod_price 進(jìn)行排序,當(dāng)價(jià)格相同的情況下阎肝,使用 prod_name 進(jìn)行排序
SELECT prod_id, prod_price, prod_name FROM Products ORDER BY 2, 3;
ORDER BY 2表示按SELECT清單中的第二個(gè)列prod_name進(jìn)行排序挤渔。ORDER BY 2,3表示先按prod_price风题,再按prod_name進(jìn)行排序判导。(不建議使用這種方式,可讀性比較差)
-
DESC 和 ASC
SELECT prod_id, prod_price, prod_name FROM Products ORDER BY prod_price DESC, prod_name;
DESC 降序沛硅,跟在字段名稱后面
DESC是 DESCENDING 的縮寫眼刃,這兩個(gè)關(guān)鍵字都可以使用。與DESC相對(duì)的是ASC(或ASCENDING)摇肌,在升序排序時(shí)可以指定它擂红。但實(shí)際 上,ASC沒有多大用處围小,因?yàn)樯蚴悄J(rèn)的昵骤。
Q:在對(duì)文本性數(shù)據(jù)進(jìn)行排序時(shí)树碱,A與a相同嗎?a位于B之前,還是Z之后 ?
A:這些問題不是理論問題变秦,其答案取決于數(shù)據(jù)庫的設(shè)置方式成榜。
在字典(dictionary)排序順序中,A被視為與a相同蹦玫,這是大多數(shù)數(shù)據(jù)庫管理系統(tǒng)的默認(rèn)行為赎婚。但是,許多DBMS允許數(shù)據(jù)庫管理員在需要時(shí)改變這種行為(如果你的數(shù)據(jù)庫包含大量外語字符钳垮,可能必須這樣做)惑淳。
-
WHERE 字句
數(shù)據(jù)庫表一般包含大量的數(shù)據(jù),很少需要檢索表中的所有行饺窿。通常只會(huì)根據(jù)特定操作或報(bào)告的需要提取表數(shù)據(jù)的子集歧焦。只檢索所需數(shù)據(jù)需要指定搜索條件(search criteria),搜索條件也稱為過濾條件(filter condition)肚医。提示:
SQL過濾與應(yīng)用過濾 數(shù)據(jù)也可以在應(yīng)用層過濾绢馍。為此,SQL的SELECT語句為客戶端應(yīng)用檢索出超過實(shí)際所需的數(shù)據(jù)肠套,然后客戶端代碼對(duì)返回?cái)?shù)據(jù)進(jìn)行循環(huán)舰涌,提取出需要的行。
通常你稚,這種做法極其不妥瓷耙。優(yōu)化數(shù)據(jù)庫后可以更快速有效地對(duì)數(shù)據(jù)進(jìn)行過濾。而讓客戶端應(yīng)用(或開發(fā)語言)處理數(shù)據(jù)庫的工作將會(huì)極大地 影響應(yīng)用的性能刁赖,并且使所創(chuàng)建的應(yīng)用完全不具備可伸縮性搁痛。此外,如果在客戶端過濾數(shù)據(jù)宇弛,服務(wù)器不得不通過網(wǎng)絡(luò)發(fā)送多余的數(shù)據(jù)鸡典,這將導(dǎo)致網(wǎng)絡(luò)帶寬的浪費(fèi)。SELECT prod_name, vend_id, prod_price FROM Products WHERE vend_id != 'DLL01'
提示: 何時(shí)使用引號(hào) ? 如果仔細(xì)觀察上述 WHERE 子句中的條件枪芒,會(huì)看到有的值括在單引號(hào)內(nèi)彻况,而有的值未括起來。單引號(hào)用來限定字符串舅踪。如果將值與字符串類型的列進(jìn)行比較纽甘,就需要限定引號(hào)。用來與數(shù)值列進(jìn)行比較的值不用引號(hào)抽碌。
SELECT prod_name, prod_price FROM Products WHERE prod_price BETWEEN 5 AND 10;
從這個(gè)例子可以看到贷腕,在使用BETWEEN時(shí),必須指定兩個(gè)值——所需范圍的低端值和高端值。這兩個(gè)值必須用AND關(guān)鍵字分隔泽裳。BETWEEN匹配范圍 中所有的值瞒斩,包括指定的開始值和結(jié)束值。
-
NULL
在創(chuàng)建表時(shí)涮总,表設(shè)計(jì)人員可以指定其中的列能否不包含值胸囱。在一個(gè)列不包含值時(shí),稱其包含空值NULL瀑梗。
NULL
無值(no value)烹笔,它與字段包含0、空字符串或僅僅包含空格不同抛丽。SELECT cust_name FROM Customers WHERE cust_email IS NULL;
確定值是否為NULL谤职,不能簡單地檢查是否= NULL。SELECT語句有一個(gè)特殊的WHERE子句亿鲜,可用來檢查具有NULL值的列允蜈。這個(gè)WHERE子句就是IS NULL子句。
-
AND
SELECT prod_id, prod_price, prod_name FROM Products WHERE vend_id = 'DLL01' AND prod_price < 5;
此SQL語句檢索由供應(yīng)商DLL01制造且價(jià)格小于等于4美元的所有產(chǎn)品的名稱和價(jià)格蒿柳。這條SELECT語句中的WHERE子句包含兩個(gè)條件饶套,用AND關(guān)鍵 字聯(lián)結(jié)在一起。AND指示DBMS只返回滿足所有給定條件的行垒探。如果某個(gè)產(chǎn)品由供應(yīng)商DLL01制造妓蛮,但價(jià)格高于4美元,則不檢索它圾叼。類似地蛤克,如 果產(chǎn)品價(jià)格小于4美元,但不是由指定供應(yīng)商制造的也不被檢索
-
OR
符合任何一個(gè)條件的結(jié)果都會(huì)被檢索出來
SELECT prod_name, vend_id, prod_price FROM Products WHERE vend_id = 'DLL01' OR vend_id = 'BRS01'
把廠商是 DLL01 或者是 BRS01 的商品檢索出來
-
求值順序
SELECT prod_name, vend_id, prod_price FROM Products WHERE (vend_id = 'DLL01' OR vend_id = 'BRS01') AND prod_price > 10;
當(dāng) AND 和 OR 搭配使用的時(shí)候夷蚊,需要注意他們的優(yōu)先級(jí)咖耘,AND 的優(yōu)先級(jí)要比 OR 的高,所以有時(shí)候需要用 () 來約束查詢子條件
假如需要列出價(jià)格為10美元及以上撬码,且由 DLL01 或 BRS01 制造的所有產(chǎn)品,需要用到下面的 SQL -
IN
SELECT prod_name, vend_id, prod_price FROM Products WHERE vend_id IN ('DLL01', 'BRS01')
SELECT prod_name, vend_id, prod_price FROM Products WHERE vend_id = 'DLL01' OR vend_id = 'BRS01'
上面兩個(gè) SQL 是一個(gè)意思
為什么要使用IN操作符?其優(yōu)點(diǎn)為:
- 在有很多合法選項(xiàng)時(shí)版保,IN操作符的語法更清楚呜笑,更直觀。
- 在與其他AND和OR操作符組合使用IN時(shí)彻犁,求值順序更容易管理叫胁。
- IN操作符一般比一組OR操作符執(zhí)行得更快(在上面這個(gè)合法選項(xiàng)很少的例子中,你看不出性能差異)汞幢。
- IN的最大優(yōu)點(diǎn)是可以包含其他SELECT語句驼鹅,能夠更動(dòng)態(tài)地建立WHERE子句。第11課會(huì)對(duì)此進(jìn)行詳細(xì)介紹。
-
NOT
SELECT prod_name, vend_id, prod_price FROM Products WHERE NOT vend_id = 'DLL01'
WHERE子句中的NOT操作符有且只有一個(gè)功能输钩,那就是否定其后所跟的任何條件豺型。因?yàn)镹OT從不單獨(dú)使用(它總是與其他操作符一起使用),所以
它的語法與其他操作符有所不同买乃。NOT關(guān)鍵字可以用在要過濾的列前姻氨,而不僅是在其后。為什么使用NOT?
對(duì)于這里的這種簡單的WHERE子句剪验,使用NOT確實(shí)沒有什么優(yōu)勢(shì)肴焊。但在更復(fù)雜的子句中,NOT是非常有用的功戚。例如娶眷,在與IN操作 符聯(lián)合使用時(shí),NOT可以非常簡單地找出與條件列表不匹配的行啸臀。 -
通配符
-
%
SELECT prod_name, prod_price FROM Products WHERE prod_name LIKE 'Fish%';
在搜索串中届宠,%表示任何字符出現(xiàn)任意次數(shù)
-
_
SELECT prod_name, prod_price FROM Products WHERE prod_name LIKE '__ inch teddy bear';
下劃線的用途與%一樣,但它只匹配單個(gè)字符壳咕,而不是多個(gè)字符
注意:
不要過度使用通配符席揽。如果其他操作符能達(dá)到相同的目的,應(yīng)該使用其他操作符谓厘。
在確實(shí)需要使用通配符時(shí)幌羞,也盡量不要把它們用在搜索模式的開始處。把通配符置于開始處竟稳,搜索起來是最慢的属桦。 仔細(xì)注意通配符的位置。如果放錯(cuò)地方他爸,可能不會(huì)返回想要的數(shù)據(jù)聂宾。
-
-
算數(shù)計(jì)算
SELECT prod_id, quantity, item_price, quantity * item_price AS expanded_price FROM OrderItems WHERE order_num = 20008
可以在查詢的字段里面執(zhí)行 加減乘除 運(yùn)算
-
文本函數(shù)
-
upper 將字符串轉(zhuǎn)換為大寫
SELECT vend_name, upper(vend_name) AS vend_name_upper FROM Vendors;
LTRIM() 去掉字符串左邊的空格
RTRIM() 去掉字符串右邊的空格
-
CONCAT() 連接字符串
SELECT concat(vend_name, '(', vend_country, ')') FROM Vendors;
可以把搜索的數(shù)據(jù)進(jìn)行一個(gè)格式化,省了一步在java中的操作
-
-
時(shí)間函數(shù)
例如數(shù)據(jù)值為:2012-05-01 00:00:00 诊笤,下面每個(gè)函數(shù)取時(shí)間里面不同的年月日
year() month() day()
SELECT order_num, cust_id FROM Orders WHERE year(order_date) = 2012
-
數(shù)值處理函數(shù)
ABS() 返回一個(gè)數(shù)的絕對(duì)值
SQRT() 返回一個(gè)數(shù)的平方根
-
統(tǒng)計(jì)函數(shù)
- AVG() 返回某列的平均值
SELECT avg(prod_price) AS avg_price FROM Products WHERE vend_id = 'DLL01'
注意:
AVG() 只能用來確定特定數(shù)值列的平均值系谐,而且列名必須作為函數(shù)參數(shù)給出。為了獲得多個(gè)列的平均值讨跟,必須使用多個(gè)AVG()函數(shù)纪他。
-
AVG() 函數(shù)忽略列值為NULL的行
?
- COUNT() 返回某列的行數(shù)
- 使用COUNT(*)對(duì)表中行的數(shù)目進(jìn)行計(jì)數(shù),不管表列中包含的是空值(NULL)還是非空值晾匠。
- 使用COUNT(column)對(duì)特定列中具有值的行進(jìn)行計(jì)數(shù)茶袒,忽略NULL值。
SELECT count(*) FROM Customers; SELECT count(cust_email) FROM Customers;
?
- max() / min()
MAX()一般用來找出最大的數(shù)值或日期值,MIN() 相反
SELECT max(prod_price) AS max_price FROM Products;
- sum()
SELECT sum(quantity * OrderItems.item_price) AS total_price FROM OrderItems WHERE order_num = '20008';
- DISTINCT 在函數(shù)中的作用
SELECT avg(DISTINCT prod_price) AS avg_distinct FROM Products;
這里先對(duì) prod_price 進(jìn)行一遍去重凉馆,然后再計(jì)算平均值
- 組合函數(shù)使用
SELECT count(*) AS num_items, max(prod_price) AS price_min, AVG(prod_price) AS price_avg FROM Products;
-
GROUP BY
-
創(chuàng)建分組
SELECT vend_id, count(*) AS num_prod FROM Products GROUP BY vend_id;
-
過濾分組
SELECT vend_id, count(*) AS num_prod FROM Products WHERE prod_price > 4 GROUP BY vend_id HAVING count(*) > 2;
HAVING 對(duì)分組后的數(shù)據(jù)進(jìn)行過濾
注意:
- GROUP BY子句可以包含任意數(shù)目的列薪寓,因而可以對(duì)分組進(jìn)行嵌套亡资,更細(xì)致地進(jìn)行數(shù)據(jù)分組。
- 如果在GROUP BY子句中嵌套了分組向叉,數(shù)據(jù)將在最后指定的分組上進(jìn)行匯總锥腻。換句話說,在建立分組時(shí)植康,指定的所有列都一起計(jì)算(所以不能從個(gè)別的列取回?cái)?shù)據(jù))旷太。
- GROUP BY子句中列出的每一列都必須是檢索列或有效的表達(dá)式(但不能是聚集函數(shù))。如果在SELECT中使用表達(dá)式销睁,則必須在GROUP BY子 句中指定相同的表達(dá)式供璧。不能使用別名。
- 大多數(shù)SQL實(shí)現(xiàn)不允許GROUP BY列帶有長度可變的數(shù)據(jù)類型(如文本或備注型字段)冻记。 除聚集計(jì)算語句外睡毒,SELECT語句中的每一列都必須在GROUP BY子句中給出。 如果分組列中包含具有NULL值的行冗栗,則NULL將作為一個(gè)分組返回演顾。如果列中有多行NULL值,它們將分為一組隅居。
- GROUP BY子句必須出現(xiàn)在WHERE子句之后钠至,ORDER BY子句之前。
-
-
子查詢
利用子查詢進(jìn)行過濾:
Q:列出訂購物品RGAN01的所有顧客SELECT cust_name, cust_contact FROM Customers WHERE cust_id IN (SELECT cust_id FROM Orders WHERE order_num IN (SELECT order_num FROM OrderItems WHERE prod_id = 'RGAN01'));
警告:
只能單列作為子查詢的SELECT語句,企圖檢索多個(gè)列將返回錯(cuò)誤
性能:
在WHERE子句中使用子查詢能夠編寫出功能很強(qiáng)且很靈活的SQL語句胎源。對(duì)于能嵌套的子查詢的數(shù)目沒有限制棉钧,不過在實(shí)際使用時(shí)由于性能 的限制,不能嵌套太多的子查詢涕蚤。 -
連接
SELECT vend_name, prod_name, prod_price FROM Vendors, Products WHERE Vendors.vend_id = Products.vend_id;
返回笛卡兒積的聯(lián)結(jié)宪卿,也稱叉聯(lián)結(jié)(cross join)
使用 WHERE 條件就是對(duì)兩個(gè)表形成的笛卡爾積進(jìn)行一次篩選
笛卡兒積(cartesian product)
由沒有聯(lián)結(jié)條件的表關(guān)系返回的結(jié)果為笛卡兒積。檢索出的行的數(shù)目將是第一個(gè)表中的行數(shù)乘以第二個(gè)表中的行數(shù)万栅。?
內(nèi)連接
SELECT vend_name, prod_name, prod_price FROM Vendors INNER JOIN Products ON Vendors.vend_id = Products.vend_id;
下面兩種SQL執(zhí)行出來的結(jié)果是一樣的
SELECT cust_name, cust_contact FROM Customers WHERE cust_id IN (SELECT cust_id FROM Orders WHERE order_num IN (SELECT order_num FROM OrderItems WHERE prod_id = 'RGAN01'));
SELECT cust_name, cust_contact FROM Customers, Orders, OrderItems WHERE Customers.cust_id = Orders.cust_id AND Orders.order_num = OrderItems.order_num AND prod_id = 'RGAN01';
?
自連接
Q:給與Jim Jones同一公司的所有顧客發(fā)送一封信件
SELECT c1.cust_name, c1.cust_contact, c1.cust_email FROM Customers AS c1, Customers AS c2 WHERE c1.cust_name = c2.cust_name AND c2.cust_contact = 'Jim Jones';
自聯(lián)結(jié)通常作為外部語句佑钾,用來替代從相同表中檢索數(shù)據(jù)的使用子查詢語句。雖然最終的結(jié)果是相同的烦粒,但許多DBMS處理聯(lián)結(jié)遠(yuǎn)比處理子 查詢快得多休溶。應(yīng)該試一下兩種方法,以確定哪一種的性能更好扰她。
?
外鏈接
SELECT Customers.cust_id, Orders.order_num FROM Customers LEFT JOIN Orders ON Customers.cust_id = Orders.cust_id
上面的例子使用LEFT OUTER JOIN從FROM子句左邊的表(Customers表) 中選擇所有行兽掰。為了從右邊的表中選擇所有行,需要使用RIGHT OUTER JOIN
Q:統(tǒng)計(jì)每個(gè)客戶的訂單數(shù)
SELECT Customers.cust_id, count(order_num) AS order_num FROM Customers LEFT JOIN Orders ON Customers.cust_id = Orders.cust_id GROUP BY Orders.cust_id;
-
插入數(shù)據(jù)
INSERT INTO Customers (cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country) VALUES ('1000000006', 'Toy Land', '123 Any Street', 'New York', 'NY', '11111', 'USA');
注意:要寫列名义黎,不要一套數(shù)據(jù)庫的表字段結(jié)構(gòu)
INSERT SELECT
可以把查詢到的數(shù)據(jù),一次性的插入豁跑,了解即可提示:
INSERT SELECT 中的列名 為簡單起見廉涕,這個(gè)例子在INSERT和SELECT語句中使用了相同的列名泻云。但是,不一定要求列名匹配狐蜕。事實(shí)上宠纯,DBMS一點(diǎn)兒也不關(guān)心SELECT返 回的列名。它使用的是列的位置层释,因此SELECT中的第一列(不管其列名)將用來填充表列中指定的第一列婆瓜,第二列將用來填充表列中指定的 第二列,如此等等贡羔。 -
復(fù)制表
CREATE TABLE CustNew AS SELECT * FROM Customers;
創(chuàng)建一個(gè)表 CustNew 廉白,把 Customers 內(nèi)的數(shù)據(jù)復(fù)制一份過去
任何SELECT選項(xiàng)和子句都可以使用,包括WHERE和GROUP BY; 可利用聯(lián)結(jié)從多個(gè)表插入數(shù)據(jù); 不管從多少個(gè)表中檢索數(shù)據(jù)乖寒,數(shù)據(jù)都只能插入到一個(gè)表中猴蹂。
提示:進(jìn)行表的復(fù)制
復(fù)制表數(shù)據(jù)是試驗(yàn)新SQL語句前進(jìn)行表復(fù)制的很好工具。先進(jìn)行復(fù)制楣嘁,可在復(fù)制的數(shù)據(jù)上測(cè)試SQL代碼磅轻,而不會(huì)影響實(shí)際的數(shù)據(jù)。 -
更新表
Q: 修改id是 1000000001 的顧客郵箱
UPDATE Customers SET cust_email = 'zz@qq.com' WHERE cust_id = '1000000001';
UPDATE Customers SET cust_email = 'zz@qq.com', cust_name = 'zl' WHERE cust_id = '1000000001';
-
刪除表數(shù)據(jù)
DELETE FROM Customers WHERE cust_id = '1000000006';
重要:
除非確實(shí)打算更新和刪除每一行逐虚,否則絕對(duì)不要使用不帶WHERE子句的UPDATE或DELETE語句聋溜。
保證每個(gè)表都有主鍵(如果忘記這個(gè)內(nèi)容,請(qǐng)參閱第12課)叭爱,盡可能像WHERE子句那樣使用它(可以指定各主鍵撮躁、多個(gè)值或值的范圍)。
在UPDATE或DELETE語句使用WHERE子句前涤伐,應(yīng)該先用SELECT進(jìn)行測(cè)試馒胆,保證它過濾的是正確的記錄,以防編寫的WHERE子句不正確凝果。
使用強(qiáng)制實(shí)施引用完整性的數(shù)據(jù)庫(關(guān)于這個(gè)內(nèi)容祝迂,請(qǐng)參閱第12課),這樣DBMS將不允許刪除其數(shù)據(jù)與其他表相關(guān)聯(lián)的行器净。
有的DBMS允許數(shù)據(jù)庫管理員施加約束型雳,防止執(zhí)行不帶WHERE子句的UPDATE或DELETE語句。如果所采用的DBMS支持這個(gè)特性山害,應(yīng)該使用它纠俭。 -
視圖
CREATE VIEW CustomProducts AS SELECT cust_name, cust_contact, prod_id FROM Customers, Orders, OrderItems WHERE Customers.cust_id = Orders.cust_id AND OrderItems.order_num = Orders.order_num;
視圖為虛擬的表。它們包含的不是數(shù)據(jù)而是根據(jù)需要檢索數(shù)據(jù)的查詢浪慌。視圖提供了一種封裝SELECT語句的層次冤荆,可用來簡化數(shù)據(jù)處理,重新格式化或保護(hù)基礎(chǔ)數(shù)據(jù)权纤。
?
?
?
?