mysql基礎,mysql必知必會
如果你喜歡,可以關注我的公眾號
第一章:SQL語句及其種類
SQL用關鍵字,表明,列名等組合而成的一條語句來描述操作的內容,關鍵字是指那些含義或使用方法事先已經定義好的英語單詞,例如"對錶進行查詢"或者"參考這張表"等包含各種意義的關鍵字
-
DDL(Data Defintion Language,資料定義語言)
DDL(資料庫定義語言)用來建立或者刪除儲存資料使用的資料庫以及資料庫中的表等物件.DDL包含以下幾種指令
- CREATE:建立資料庫和表物件
- DROP:刪除資料庫和表物件
- ALTER:修改資料庫和表物件的結構
-
DML(Data Manipulation Language,資料操作語言)
用來查詢或變更表中的記錄
- SELECT:查詢表中的資料
- INSERT:向表中插入資料
- UPDATE:修改表中的資料
- DELETE:刪除表中的資料
-
DCL(Data Control Language,資料控制語言)
用來確認或者取消對資料庫中的資料進行的變更.除此之外,還可以用使用者是否有許可權操作資料庫進行設定
- COMMIT: 確認對資料庫中的資料進行的變更
- ROLLBACK: 取消對資料庫中的資料進行的表更
- GRANT: 賦予使用者操作的許可權
- REVOKE: 取消使用者的操作許可權
-
實際應用中我們其實95%的時候都是用到DML
SQL書寫基本規則
-
sql語句要以分號(;)結束
-
sql語句不區分大小寫
sql語句不區分大小寫,例如SELECT或者select,解釋都是一樣的,但是為了理解起來更容易,還是建議關鍵字都大寫 -
常數的書寫方式是固定的
常見的常數有字串,日期或者數字等等
- sql語句中有字串的時候,需要像'abc'這樣,使用單引號括起來
- sql語句中含有日期的時候也是以單引號括起來
- sql語句中需要書寫數字的時候,不需要使用任何記號標識,直接寫成1000數字即可
-
單詞需要用空格或者換行來分離
表的建立
商品編號 | 商品名稱 | 商品分類 | 銷售單價 | 進貨單價 | 登記日期 |
---|---|---|---|---|---|
0001 | T恤衫 | 衣服 | 1000 | 500 | 2018-12-24 |
0002 | 打孔器 | 辦公用品 | 500 | 320 | 2018-12-12 |
0003 | 運動T恤 | 衣服 | 4000 | 2800 | |
0004 | 菜刀 | 廚房用具 | 3000 | 2800 | 2018-12-24 |
0005 | 高壓鍋 | 廚房用具 | 6800 | 5000 | 2018-06-24 |
0006 | 叉子 | 廚房用具 | 500 | 2018-12-24 | |
0007 | 擦菜板 | 廚房用具 | 880 | 790 | 2018-04-01 |
0008 | 圓珠筆 | 辦公用品 | 100 | 2018-10-01 |
- 接下來我們就建立上面的這張表,
-
資料庫的建立(CREAT DATABASES 語句)
- 語法
CREATE DATABASES <資料庫名稱> ;
建立資料庫shop的語句
CREATE DATABASES shop ;
-
表的建立(CREAT TABLE 語句)
- 語法
CREATE DATABASES <表名>
(<列名1> <資料型別> <該列所需的約束>,
<列名2> <資料型別> <該列所需的約束>,
<列名3> <資料型別> <該列所需的約束>,
<列名4> <資料型別> <該列所需的約束> ...
<該表的約束1>,<該表的約束2>...);
建立表Shopin的語句
CREATE TABLE Shopin (
shopin_id CHAR(4) NOT NULL,
shopin_mei VARCHAR(255) NOT NULL,
shopin_bunrui VARCHAR(255) NOT NULL,
hanbai_tanka INTEGER ,
shiire_tanka INTEGER ,
tprokubi DATE,
PRIMARY KEY (shopin_id) ) ;
-
命名規則
資料庫名稱,表名和列名等可以使用這種規則:
- 半形英文字母
- 半形數字
- 下劃線(_)
- 名稱必須以英文字母作為開頭,不是說不能以數字開頭,是可以的,但是還是要符合sql標準
- 名稱不能重複
-
主鍵(PRIMARY KEY)
表中的每一行都應該有唯一標識自己的一列,其值能夠區分表中的每一行,沒有主鍵,更新或刪除表中特定行很困難
- 任意兩行都不具有相同的主鍵值
- 每個行都必須具有一個主鍵值(主鍵值不允許為NULL)
資料型別的指定
-
INTEGER
用來儲存整數列的資料型別,不能儲存小數 -
CHAR
CHAR是CHARACTER的簡稱,用來儲存字串的列的資料型別,括號中指定的是該列可以儲存字串的最大長度,字串超出最大長度的部分是無法輸入到該列中的,如果我們設定的長度是8,而我們儲存的資料是'abc',資料庫會以'abc| | | | | |'(abc後面有5個空格)的形式儲存起來, -
VARCHAR
同CHAR一樣,但是該型別是以可變長字串形式來儲存的,例如我們存入'abc'的時候,儲存的就是字串abc,不會有空格
表刪除和更新
-
表的刪除(DROP TABLE語句)
語法
DROP TABLE <表名>;
刪除Shopin表
DROP TABLE Shopin;
-
表的更新操作(ALTER TABLE語句)
語法
ALTER TABLE <表名> ADD COLUMN <列的定義>;
- 新增一列可以儲存100可變長的字串mei_kana列
ALTER TABLE Shopin ADD COLUMN mei_kana VARCHAR(100);
- 刪除列
ALTER TABLE <表名> DROP COLUMN <列名>;
刪除我們剛才建立的列
ALTER TABLE Shopin DROP COLUMN mei_kana;
-
向表中插入資料
語法
INSERT INTO <表名> VALUES (....);
向shopin表中插入資料
這裡是一共上面8條資料的inset語句
INSERT INTO `shop`.`shopin`(`shopin_id`, `shopin_mei`, `shopin_bunrui`, `hanbai_tanka`, `shiire_tanka`, `tprokubi`) VALUES ('0001', 'T恤衫', '衣服', 1000, 500, '2018-12-24');
INSERT INTO `shop`.`shopin`(`shopin_id`, `shopin_mei`, `shopin_bunrui`, `hanbai_tanka`, `shiire_tanka`, `tprokubi`) VALUES ('0002', '打孔器', '辦公用品', 500, 320, '2018-12-12');
INSERT INTO `shop`.`shopin`(`shopin_id`, `shopin_mei`, `shopin_bunrui`, `hanbai_tanka`, `shiire_tanka`) VALUES ('0003', '運動T恤', '衣服', 4000, 2800);
INSERT INTO `shop`.`shopin`(`shopin_id`, `shopin_mei`, `shopin_bunrui`, `hanbai_tanka`, `shiire_tanka`, `tprokubi`) VALUES ('0004', '菜刀', '廚房用具', 3000, 2800, '2018-12-24');
INSERT INTO `shop`.`shopin`(`shopin_id`, `shopin_mei`, `shopin_bunrui`, `hanbai_tanka`, `shiire_tanka`, `tprokubi`) VALUES ('0005', '高壓鍋', '廚房用具', 6800, 5000, '2018-06-24');
INSERT INTO `shop`.`shopin`(`shopin_id`, `shopin_mei`, `shopin_bunrui`, `hanbai_tanka`, `tprokubi`) VALUES ('0006', '叉子', '廚房用具', 500, '2018-12-24');
INSERT INTO `shop`.`shopin`(`shopin_id`, `shopin_mei`, `shopin_bunrui`, `hanbai_tanka`, `shiire_tanka`,`tprokubi`) VALUES ('0007', '擦菜板', '廚房用具', 880,790, '2018-04-01');
INSERT INTO `shop`.`shopin`(`shopin_id`, `shopin_mei`, `shopin_bunrui`, `hanbai_tanka`, `tprokubi`) VALUES ('0008', '圓珠筆', '辦公用品', 100, '2018-10-01');
SELECT語句基礎
-
列的查詢
- 在日常使用中,SELECT使用的最多,基本語法如下
SELECT <列名>,... FROM <表名>;
- 從Shopin表中查詢商品編號,名稱和進貨單價
SELECT shopin_id,shopin_mei,shiire_tanka FROM Shopin;
- 在這裡也可以使用'*',代表的是所有的列
-
為列設定別名
這個AS可以後面可以跟英文和中文,中文的話使用雙引號引起來
SELECT
shopin_id AS "商品編號",
shopin_mei AS "商品名稱",
shiire_tanka AS "進貨單價"
FROM Shopin;
-
常數的查詢
常熟查詢就是查的時候多出來一列裡面的內容就是我們自定義好的內容
SELECT
'商品' AS mo ,
shopin_id , shopin_mei
FROM Shopin;
通過上面的sql語句查出來的就會多出來一個mo的列,裡面的值都是商品
-
從查詢結果中刪除重複行
這裡需要說明下是從select語句中刪除重複的行,而不是刪除資料庫中的資料,如果有兩條都是null,也會刪除重複
SELECT DISTINCT <列名>,<列名>... FROM <表名>
-
根據WHERE語句來選擇記錄
WHERE語句其實就是根據條件去查詢,比如說,我們想查詢成績是65的學生等等,檢視語法
SELECT <列名>... FROM <表名> WHERE <條件表示式>;
我們根據上面的Shopin表查詢所有品類是衣服的
SELECT * FROM Shopin WHERE shipin_bunrui = '衣服';
這裡是先通過where語句查詢出所有的記錄,然後再根據指定的條件去查詢
-
限制結果
SELECT * FROM Shopin LIMIT 5;
此執行結果是查到第一行到第五行的資料,拿到下一個5行
SELECT * FROM Shopin LIMIT 5,5;
這個語句一般用於分頁上,檢索出第一行是0而不是1,因此LIMIT1,1將檢索出第二行而不是第一行
-
註釋的書寫方法
註釋的方法有以下幾種
- 書寫在"-- "之後,只能註釋一行
- 書寫在"# "之後,只能註釋一行
- 書寫在/* 和 */之間,可註釋多行
第二章:算數運算子和比較運算子
-
算數表示式
含義 | 運算子 |
---|---|
加法運算 | + |
減法運算 | - |
乘法運算 | * |
除法運算 | / |
這裡看一個例子
SELECT age*2 FROM person
這個語句就是查詢了年齡乘以2後的結果,當然,也可以使用括號運算子,括號運算子可以指定優先順序比如(1+2)*3
-
需要注意null
這裡需要說明下,所有包含為null的計算,結果肯定的是null,那我們有的小夥伴就有點奇怪了,我們很多時候想通過 5 +null得到5這樣的結果該怎麼辦呢,接著往下看,後面會介紹到
-
比較運算子
含義 | 運算子 |
---|---|
和~相等 | = |
和~不相等(等同於!=) | <> |
大於等於~ | >= |
大於~ | > |
小於等於~ | <= |
小於~ | < |
這些運算子可以對整數,字元,還有日期幾乎所有的資料型別都可以進行比較
-
對字串使用運算子時需要注意的事項
chr(字串型別) |
---|
1 |
2 |
3 |
10 |
12 |
222 |
- 這裡我們執行大於'2'的操作會得到什麼樣的結果呢
- 所得到的結果是 3,222
- 沒想到吧,是不是覺得10和12都比2大,所有應該選出來呢,大家之所以會混淆大概是因為數字和字串的緣故,也就是說2和'2'並不一樣
- 之所以10和12沒有選出來,是因為他們是以1開頭的,這就像在字典中"提問","提議"."問題"按照以下順序排列一樣,"提問","提議","問題"
- 或者我們以書籍的章節為列也可以,1-2節包含在第一章當中,所以肯定比第二章更靠前
-
不能對null使用比較運算子
先舉幾個例子
- 查詢某種單價不等於20的商品
SELECT * FROM Shopin WHERE shiire_tanka <> 20;
如果單價裡面有null的時候,這裡是不會顯示出來的,大家可以去做下實驗
- 那我們是否想到了另一種方法呢
SELECT * FROM Shopin WHERE shiire_tanka = null;
執行完之後返回一條記錄都沒有
- sql不識別"=null"和"<>null"
- sql給我們專門提供了判斷是否為空的運算子IS NULL,想要選取null記錄時如下
SELECT * FROM Shopin WHERE shiire_tanka IS NULL;
- 反之 IS NOT NULL運算子,對null的運算子還有很多,將會在後面做出說明
邏輯運算子
-
NOT運算子
NOT運算子是用來否定某一個條件,但是不能濫用
- 先看下下面的例子
SELECT * FROM Shopin WHERE hanbai_tanka >= 1000;
這個語句是查詢單價大於等於1000的記錄
- 在這裡加上NOT
SELECT * FROM Shopin WHERE NOT hanbai_tanka >= 1000;
執行完之後,發現結果是單價小於1000的,等價於
SELECT * FROM Shopin WHERE hanbai_tanka < 1000;
通過上面的例子我們可以發現,不使用NOT運算子也可以編出有效果的相同的查詢條件.不僅如此,不使用NOT運算子的查詢條件更容易讓人理解,使用NOT運算子時,我們不得不每次都在大腦中進行"大於等於1000以上這個條件的否定結果就是小於1000"這樣的轉換
雖然如此,但是也不能否定NOT運算子的作用,在編寫複雜的sql時,經常會用到NOT的身影,這裡只是希望大家瞭解NOT運算子的書寫方法和工作原理,同時提醒大家不要濫用該運算子
-
AND和OR運算子
- AND運算子在其兩側的查詢條件都成立時整個查詢條件才成立,其意思相當於並且,語法
SELECT <列名> FROM <表名> WHERE <條件> AND <條件>;
- OR運算子是在其兩側的查詢條件有一個成立時整個查詢條件都成立,其意思是相當於或者
SELECT <列名> FROM <表名> WHERE <條件> OR <條件>;
- AND運算子優於OR運算子,想要先執行OR運算子時可以使用括號
第三章:對錶進行聚合查詢
-
聚合函式
通過對sql資料進行操作或計算時使用函式,計算表中全部資料行數時,可以使用COUNT函式.該函式就是使用COUNT來命名的,除此之外,SQL中還有很多其他用於合計的函式,請大家先記住以下5個常用的函式
- COUNT:計算表中的記錄數(行數)
- SUM:計算表中數值列的資料總和
- AVG:計算表中數值列的資料的平均值
- MAX:計算表中數值列的資料的最大值
- MIN:計算表中數值列的資料的最小值
-
計算表中資料的行數
SELECT COUNT(*) FROM Shopin; //計算全部資料的行數
COUNT函式的結果根據引數的不同而不同,COUNT(*)會得到包含NULL的資料的行數,而COUNT(<列名>)會得到NULL之外的資料行數
-
計算總和
SELECT SUM(<列名>) FROM <表名>;
-
計算平均值
SELECT AVG(<列名>) FROM <表名>;
計算平均值,如果有的列是null,是不會計算在內的
-
計算最大值和最小值
SELECT MAX(<列名>) FROM <表名>; //最大值
SELECT MIN(<列名>) FROM <表名>; //最小值
max/min適用於所有資料型別的列,sum/avg函式只適用於數值型別的列
-
使用聚合函式刪除重複值(關鍵字DISTINCT)
前面我們已經瞭解了刪除重複值關鍵字DISTINCT
- 舉個例子,我們上面的shopin表中有好多商品分類都是相同的,我們用sql語句查下她一共有幾個分類
SELECT COUNT(DISTINCT shopin_bunrui) FROM Shopin;
這個就是刪除重複值,在計算所有總行數之前先把重複的值刪掉 在聚合函式的引數中使用DISTINCT,可以刪除重複資料,對sum/avg都有效
對錶進行分組
-
GROUP BY 子句
下面我們把表分成幾組,然後再進行聚合處理,也就是按照"商品種類","登記日期"等進行聚合,語法如下
SELECT <列名>,<列名>... FROM <表名> GROUP BY <列名> ,<列名> ...
下面我們來統計下商品種類的資料行數
SELECT shopin_bunrui, COUNT(*)
FROM Shopin
GROUP BY shopin_bunrui
執行結果
shopin_bunrui | COUNT |
---|---|
衣服 | 2 |
辦公用品 | 2 |
廚房用具 | 4 |
如上所示,未使用GROUP BY時,結果只有1行,而這次結果是多行,這個是因為不使用GROUP BY子句時,是將表中的所有資料作為一個組來對待的,使用了之後,會將表中的資料分為多個組進行處理,像切蛋糕一樣進行了分組,在GROUP BY子句中指定的列稱為聚合鍵或者分組列..GROUP BY就像是切分表的一把刀
當聚合鍵中存在有NULL的時候,在結果中會以空行的形式表現出來
-
使用WHERE子句時GROUP BY的執行結果
語法如下
SELECT <列名>,<列名>... FROM <表名> WHERE <條件表示式> GROUP BY <列名> ,<列名> ...
像這樣使用WHERE進行聚合處理時,會先通過WHERE子句指定的條件進行過濾然後再進行聚合處理,看下面的例子
SELECT shiire_tanka,COUNT(*) FROM Shopin WHERE shopin_bunrui = '衣服' GROUP BY shiire_tanka
上面這段程式碼首先是使用了WHERE對記錄進行了過濾,查詢到資料庫中的記錄
shopin_bunrui(商品分類) | shopin_mei(商品名稱) | shiire_tanka(進貨單價) |
---|---|---|
衣服 | T恤衫 | 500 |
衣服 | 運動T恤 | 2800 |
然後再進行進貨單價對兩條記錄進行處理,得到如下結果
shiire_tanka(進貨單價) | count(*) |
---|---|
500 | 1 |
2800 | 1 |
GROUP BY與WHERE 並用時SELECT語句的執行順序
FROM - WHERE - GROUP BY - SELECT
-
使用聚合函式和GROUP BY時常見的錯誤
-
常見錯誤1:在SELECT中書寫了多餘的列
在使用COUNT這樣的聚合函式時,SELECT子句中元素室友嚴格的限制,實際上,使用聚合函式時,SELECT 子句中只能存在以下幾種元素
- 常數
- 聚合函式
- GROUP BY 子句中指定的列名 這裡我們想一想也就明白了,比如查詢商品名稱和總行數,那名稱這一列該顯示什麼名字呢,那麼多的名稱都顯示出來嗎,顯然是不可能的 使用GROUP BY子句時,SELECT子句中不能出現聚合鍵之外的列名
-
常見錯誤2:在GROUP BY中書寫了別名
SELECT shiire_tanka AS sb , COUNT(*) FROM Shopin GROUP BY sb;
上述的程式碼在MySQL裡執行是沒有什麼問題的,可以正常執行,但是這樣的寫法是不便於閱讀的,因此還是請大家不要使用
-
常見錯誤3:在WHERE子句中使用聚合函式
先看下下面的程式碼
SELECT category_id ,COUNT(*) FROM blog WHERE COUNT(*) = 2 GROUP BY category_id
遺憾的是,這樣的SELECT在執行時發生了錯誤 只有SELECT子句在HAVING子句或者ORDER BY子句中能夠使用聚合函式
-
在這裡就引出了一個問題
可能有的小夥伴就能發現,我們在前面使用的DISTINCT和所學的GROUP BY,都能夠刪除後序列中的重複資料,檢視以下程式碼
SELECT DISTINCT shopin_hunrui FROM Shopin;
SELECT shopin_hunrui FROM Shopin GROUP BY shopin_hunrui;
這兩個程式碼執行後的結果都是相同的,其實不僅是執行結果,執行速度上也基本差不多,到底使用哪一種呢?
不引用COUNT等聚合函式,而只使用GROUP BY子句的SELECT語句,會讓人覺得非常奇怪,難免會讓人產生"為什麼要對錶進行分組呢?這樣有必要嗎?"等疑問,SQL語句語法與英語十分相似,理解起來非常容易,希望大家不要浪費這一優勢,編寫出一些難以理解的SQL語句
為聚合結果指定條件
-
HAVING子句
給GROUP BY分組後的結果指定條件,語法如下
SELECT <列名>,<列名>... FROM <表名> GROUP BY <列名>,<列名>... HAVING <條件>;
HAVING子句必須在GROUP BY之後,HAVING要寫在GROUP BY之後 接下來就讓我們練習下HAVING子句吧
SELECT shopin_bunrui ,COUNT(*) FROM Shopin GROUP BY shopin_bunrui HAVING COUNT(*) = 2;
這裡我就不寫執行結果了,大家可以去測試,意思就是說對我們剛才的GROUP BY加了一層過濾條件,只有滿足條件COUNT(*)=2的才能查詢出來
-
HAVING子句的構成元素
HAVING子句和包含GROUP BY子句時的SELECT子句一樣,能夠使用的元素有一定的限制,限制內容也是完全相同的,HAVING能夠使用的元素如下
- 常數
- 聚合函式
- GROUP BY 子句指定的列名
-
相對於HAVING子句,更適合寫在WHERE子句中的條件
有些條件可以寫在HAVING子句當中,又可以寫在WHERE當中,得到的結果都是一樣的,先看下下面的程式碼
SELECT shopin_bunrui ,COUNT(*) FROM Shopin GROUP BY shopin_bunrui HAVING shopin_bunrui = '衣服';
上面的sql是獲取衣服這個分類的總條數,再看下面這個程式碼
SELECT shopin_bunrui ,COUNT(*) FROM Shopin WHERE shopin_bunrui = '衣服' GROUP BY shopin_bunrui;
上面兩個執行完後的結果
shopin_bunrui | COUNT |
---|---|
衣服 | 2 |
雖然條件寫在WHERE和HAVING子句當中,但是條件的內容,以及返回的結果完全相同,因此大家可能會覺得兩種書寫方式都沒問題
如果僅從結果來看的話,確實如此,但是筆者認為,聚合鍵所對應的條件還是應該書寫在WHERE子句當中
理由有兩個
首先,根本原因是WHERE子句和HAVING子句的作用不同,如前所述,HAVING子句是用來指定組的條件的,因此"行"所對應的條件還是應該書寫在WHERE子句當中,這樣一來,書寫出的SELECT語句不但可以分清兩者各自的功能,理解起來還更容易
當然,WHERE比HAVING的執行速度會更快一點
對查詢結果就行排序
-
ORDER BY子句
通常,從表中抽取資料時,如果沒有特別指定順序,最終排列順序便無從得知,即使是同一條SELECT語句,每次執行時排列順序很有可能發生改變
但是不進行排序很有可能出現結果混亂的情況,這時,便需要通過在SELECT語句 末尾加上ORDER BY子句來指定排列順序,語法如下
SELECT <列名>,<列名>... FROM <表名> ORDER BY <排序基準列>,<排序基準列>...;
- 按照銷售單價由低到高(升序)進行排列
SELECT * FROM Shopin ORDER BY hanbai_tanka;
執行結果我就不寫了,大家可以做做實驗
-
指定升序或降序
上面已經知道了升序排列是由小到大,降序就是由大到小,需要使用到關鍵字DESC,升序使用到的關鍵字是ASC,一般預設就是升序,所以可以省略
SELECT * FROM Shopin ORDER BY hanbai_tanka DESC;
-
指定多個鍵排序
SELECT * FROM Shopin ORDER BY hanbai_tanka , shopin_id;
做了實驗的小夥伴應該可以仔細觀察下,這個是根據單價進行由小到大的排序,如果單價有相同的話,會根據id由小到大的順序排列
-
NULL的順序
列為null時是不會進行排序的,但是也是會顯示出來到結果裡面,會在開頭或者末尾進行彙總
第四章:資料更新
資料的插入(INSERT語句的使用方法)
-
INSERT語句的基本語法
INSERT INTO <表名> (<列名>,<列名>...) VALUES (值1,值2...);
這裡舉一個例子,比如說我們想往使用者表中插入一條資料怎麼操作呢
INSERT INTO user (id,name) VALUES (1,'張三');
這樣就成功把資料新增到資料庫了,這裡其實我想說的是,可以省略表名後的列清單,這時VALUES子句的值會預設按照從左到右的順序賦給每一列
INSERT INTO user VALUES (1,'張三');
-
從其他表中複製資料
插入資料的方法,除了使用VALUES子句指定具體的資料之外,還可以從其他表中複製資料,下面我們來看下如何從一張表複製到另一張表 我做實驗的時候一共建立了兩張表,先看下
- role表
id | name |
---|---|
1 | 張三 |
2 | 李四 |
3 | 王五 |
- user表
id | name | age |
---|---|---|
user表裡是沒有資料的,我是想把role表的內容複製到user裡面, 接下來就讓我們趕快嘗試下吧
INSERT INTO user (id,name) SELECT (id,name) FROM role ;
執行完該INSERT .... SELECT語句之後,表中就多了3條資料,這個age欄位其實是我有意加的,我想試試多加了欄位可以新增成功嗎,大家也可以試試,這個語句可以在需要進行資料備份時使用
其實這裡複製資料也是可以使用WHERE.GROUP BY等等一些子句,舉個例子,比如有個商品表,想查出該表的所有分類的銷售總價和進貨總價,然後新增到另一張表中,還是之前前面學說的商品表,建立個ShopinBunrui表,我們寫個sql看看
INSERT INTO
ShopinBunrui (shop_bunrui,sum_hanbai_tanka,sum_shiire_tanka)
SELECT shop_bunrui,SUM(hanbai_tanka),SUM(shiire_tanka)
FROM Shopin
GROUP BY shop_bunrui;
資料的刪除(DELETE語句的使用方法)
-
DELETE語句的基本用法
指定刪除物件的DELETE的語句
DELETE FROM <表名> WHERE <條件>;
清空某張表,而想保留這張表的結構
DELETE FROM <表名>;
其實mysql還提供了一種只能刪除全部資料的TRUNCATE語句
TRUNCATE <表名>;
與DELETE不同的是,TRUNCATE只能刪除表中的全部資料,不能通過WHERE子句指定條件去刪除部分資料,也正是因為它不能具體控制刪除物件,所以其處理速度比DELETE要快很多,實際上,DELETE語句在DML語句中也屬於處理時間比較長的,因此需要刪除全部資料時,使用TRUNCATE可以縮短執行時間
資料的更新(UPDATE語句的使用方法)
-
UPDATE語句的基本用法
修改整張表的某個列
UPDATE <表名> SET <列名> = <表示式>;
指定條件的UPDATE語句
UPDATE <表名> SET <列名> = <表示式> WHERE <條件>;
事務
-
什麼是事務
估計大家對事務這個詞並不陌生,它通常都帶有一些商務貿易或者經濟活動的意味,但是在RDBMS中,事務代表了對錶中資料進行更新的單位,簡單來講,事務就是需要在同一個處理單元中執行的一系列更新處理的集合
如前面所述,對錶進行更新需要使用INSERT,DELETE或者UPDATE三種語句,但通常情況下,更新處理並不是執行一次就結束了,而是需要執行一系列連續的操作,這時,事務就能提現出她的價值了
說到事務的例子,請大家思考一下下述情況
現在,請大家把自己想象成管理shopin表的程式設計師或者軟體工程師,銷售部門的領導對你提出如下要求
"某某,經過會議討論,我們決定把運動褲的銷售單價下調1000元,同時把T恤的銷售單價上浮1000元,麻煩你更新下資料庫"
在這裡只需要使用UPDATE進行更新就可以了,所以肯定會直接回答"知道了,你放心吧"
此時的事務就是由如下兩條更新進行處理所組成
1.
UPDATE Shopin
SET hanbai_tanka = hanbai_tanka - 1000
WHERE shopin_mei = '運動褲';
2.
UPDATE Shopin
SET hanbai_tanka = hanbai_tanka + 1000
WHERE shopin_mei = 'T恤';
將上面的操作一定要作為同一個處理單元執行,如果只執行了1的操作而忘執行2的操作,或者反過來只執行了2的操作沒有執行1的操作,一定會收到領導的嚴厲批評,遇到這種需要在同一個處理單元中執行一系列更新操作的情況,一定要使用事務來進行處理
事務是需要在同一處理單元中執行的一系列更新處理的集合
一個事務中包含多少個更新處理或者包含那些處理,並沒有固定的標準,而是根據使用者的要求決定的
-
建立事務
如果想在DBMS中建立事務,可以按照如下語法編寫sql語句
START TRANSACTION;
DML語句;
DML語句;
DML語句;
...
事務結束語句(COMMIT或者ROLLBACK);
使用事務開始語句和事務結束語句,將一系列DML語句括起來,就實現了一個事務處理
我們對之前的商品資訊創建出事務
START TRANSACTION;
UPDATE Shopin
SET hanbai_tanka = hanbai_tanka - 1000
WHERE shopin_mei = '運動褲';
UPDATE Shopin
SET hanbai_tanka = hanbai_tanka + 1000
WHERE shopin_mei = 'T恤';
COMMIT;
- COMMIT--提交處理 COMMIT是提交事務包含的全部更新處理的結束指令,相當於檔案處理的覆蓋儲存,一旦提交,就無法恢復到事務開始前的狀態了,因此,在提交之前一定要確認是否真的需要這些更新
- ROLLBACK--取消處理 ROLLBACK是取消事務包含的全部更新處理的結束指令.相當於檔案處理中的放棄儲存,一旦回滾,資料庫就會恢復到事務開始之前的狀態,通常回滾並不會像提交那樣造成大規模的資料損失
事務回滾執行之後,表中的資料不會發生任何改變,這是因為執行最後一行的ROLLBACK之後,所有處理都被取消了
-
ACID特性
事務都遵循四種標準規格的約定,將這四種特性的首字母結合起來統稱為ACID特性,這些約定都是必須遵守的規則
- 原子性
原子性是指在事務結束時,其中所包含的更新處理要麼全部執行,要麼完全不執行的特性,也就是要麼佔有一切,要麼一無所有,例如,在之前的例子中,事務結束時,是絕對不可能出現運動褲價格下降了而T恤價格上漲了的情況該事物結束狀態,要麼兩者都執行了,要麼都不執行
- 一致性
一致性指的是事務包含的處理,要滿足資料庫提前設定的約束,如主鍵約束或者NOT NULL約束等,例如:設定了NOT NULL約束的列是不能更新為NULL的,試圖插入違反主鍵約束的記錄就會出錯,無法執行.對事務來說,這些不合法的SQL會被回滾,也就是說這些SQL處理會被取消,不會執行
- 隔離性
隔離性指的是在不同的事務之間是互不干擾的特性,該特性保證了事務之間不會相互巢狀,此外,在某個事務中進行的更改,在該事務結束之前,對其他事務而言是不可見的,因此,即使某個事務向表中添加了記錄,在沒有提交之前,其他事務是看不到新新增的記錄的
- 永續性
永續性也可以稱為耐久性,指的是事務(不論是提交還是回滾)一旦結束,DBMS會保證該時點的資料狀態得以儲存的特性.即使由於系統故障導致資料丟失,資料庫也一定能通過某種手段進行恢復
如果不能保證永續性,即使是正常提交結束的事務,一旦發生了系統故障,就會導致資料丟失,一切都需要從頭再來的後果
保證永續性的方法根據實現的不同而不同,其中最常見的事務就是將事務的執行記錄儲存到硬碟等儲存介質中(該執行記錄稱為日誌),當發生故障時,可以通過日誌恢復到故障發生前的狀態
第五章:複雜查詢
檢視
-
檢視是什麼
通俗的講,檢視就是一條SELECT語句執行後返回的結果集。所以我們在建立檢視的時候,主要的工作就落在建立這條SQL查詢語句上,檢視充當的是虛擬表的角色。
-
檢視的優點
可以將頻繁使用的SELECT語句儲存成檢視,這樣就不會每次都重新書寫了,建立好檢視後,只需在SELECT語句中進行呼叫,就可以方便的得到想要的結果了,檢視也會隨著表裡資料的更新而更新,非常方便靈活
-
建立檢視的方法
建立檢視可以通過CREATE VIEW語句來完成
CREATE VIEW 檢視名稱 (<檢視列名1>,<檢視列名2>...)
AS
<SELECT語句>
SELECT語句需要書寫在AS關鍵字之後.SELECT語句中列的排列順序和檢視中列的排列順序相同,SELECT語句中的第一列就是檢視中的第一列,以此類推,檢視的列名在檢視名稱之後的列表中定義
接下來就讓我們建立第一個檢視吧,還是之前的Shopin表
CREAT VIEW ShopinSum (shopin_bunrui,cnt_shopin)
AS
SELECT shopin_bunrui,COUNT(*)
FROM Shopin
GROUP BY shopin_bunrui;
這樣我們就在資料庫中建立了一個名為ShopinSum的檢視,此處的AS不能省略,也和使用別名時的AS不一樣,雖然很容易混淆,但是語法就是這麼規定的
- 使用檢視
SELECT shopin_bunrui,cnt_shopin FROM ShopinSum;
執行結果
shopin_bunrui | cnt_shopin |
---|---|
衣服 | 2 |
辦公用品 | 2 |
廚房用具 | 4 |
通過上述的檢視ShopinSum定義的主體(SELECT語句)我們可以看出,該檢視將根據商品種類(shopin_bunrui)統計出商品數量(cnt_shopin)作為結果儲存起來,這樣如果大家在工作中需要頻繁進行統計時,就不用每次都書寫使用GROUP BY和COUNT函式的SELECT語句
-
檢視的限制
- 定義檢視時不能使用ORDER BY子句
- 對檢視進行更新 檢視是隨著主表的更新而更新的,對檢視的更新也是有很多條件的,比如說我們使用了聚合建對檢視進行了更改,這樣就不會保證檢視和表的一致性了,下面給大家列舉一些具有代表性的條件
①.SELECT子句中未使用DISTINCT
②.FROM子句中只有一張表
③.未使用GROUP BY字句
④.未使用HAVING字句
只有滿足了以上四個條件才能對檢視進行增刪改操作
當我們對檢視就行增刪改的時候表中的資料也是會發生改變,保持一致性,對檢視進行更新歸根接地就是對錶就行更新
-
刪除檢視
DROP VIEW 檢視名稱;
子查詢
-
子查詢和檢視
前面我們學習了檢視這個非常方便的工具,本節將學習以檢視為基礎的子查詢.子查詢的特點概括起來就是一張一次性的檢視,首先我們來看一組sql語句
SELECT shopin_bunrui,cnt_shopin
FROM ( SELECT shopin_bunrui,COUNT(*) AS cnt_shopin
FROM Shopin
GROUP BY shopin_bunrui
) AS ShopinSum;
首先解釋下這個sql語句的執行流程,首先執行的是內層的查詢
SELECT shopin_bunrui,COUNT(*) AS cnt_shopin
FROM Shopin
GROUP BY shopin_bunrui
執行完成之後結果是放在別名為ShopinSum的檢視中
SELECT shopin_bunrui,cnt_shopin
FROM ShopinSum
這樣就好理解了,當然也有多層的子查詢,我們看個例子
SELECT shopin_bunrui,cnt_shopin
FROM ( SELECT * FROM
(SELECT shopin_bunrui,COUNT(*) AS cnt_shopin
FROM Shopin
GROUP BY shopin_bunrui) AS ShopinSum
WHERE cnt_shopin = 4) AS ShopinSum;
當然,隨著子查詢層數的增加,SQL語句會變得越來越難讀懂,效能也會越來越差,因此還是請儘量避免多層查詢
-
標量子查詢
標量就是單一的意思,標量子查詢就是返回單一值得子查詢,說法好像有點抽象,還是看sql語句吧
SELECT shopin_id,shopin_mei,hanbai_tanka
FROM Shopin
WHERE hanbai_tanka >(SELECT AVG(hanbai_tanka) FROM Shopin);
這個時候我們看內層的查詢,返回的結果就是單一的值,所以這個就是標量子查詢,WHERE子句後面是不能跟聚合函式的,所以我們只能通過這種方式去查
標量子查詢絕對不能返回多行結果,如果返回多行的話就會報錯
關聯子查詢
我們試著去想一個場景,就是我們想查出比該分類商品平均價格大的商品,怎麼取查詢呢
-- 計算每個平均價格
SELECT AVG(hanbai_tanka) FROM Shopin GROUP BY shopin_bunrui;
SELECT * FROM Shopin
WHERE hanbai_tanka > (SELECT AVG(hanbai_tanka) FROM Shopin GROUP BY shopin_bunrui)
我們看下這個平均價格查出來返回的是多行,通過子連結去查的話肯定是會報錯的,這個時候就要用到關聯查詢了,這個比較的抽象還是先觀察程式碼吧
SELECT * FROM Shopin AS S1
WHERE hanbai_tanka > (SELECT AVG(hanbai_tanka) FROM Shopin AS S2
WHERE S1.shopin_bunrui = S2.shopin_bunrui
GROUP BY shopin_bunrui)
這裡起到關聯作用的就是在子查詢中新增的where子句的條件,該條件的意思就是,在同一種類中對比各商品的單價和平均單價進行比較
在關聯查詢中,外面的表是不能訪問內部的表,內部可以訪問外面的
第六章:函式,謂詞,CASE表示式
各種各樣的函式
-
函式的種類
我們在之前已經看到了聚合函式,其實還有很多的函式,聚合函式基本上包括MAX,MIN,AVG,SUM,COUNT這五種,而其他種類的函式超過幾百種,雖然函式眾多,其實我們日常應用中不是很多,不熟悉的時候大家也可以去查查相關的文件,函式大致可以分為以下幾種
- 算術函式(用來進行數值計算的函式)
- 字串函式(用來進行字串操作的函式)
- 日期函式(用來進行日期操作的函式)
- 轉換函式(用來轉換資料型別和值得函式)
- 聚合函式(用來進行資料聚合的函式)
-
算術函式
不知道大家對前面的+ - * /還有印象嗎,其實那個就是算數函式,我們看看一些常用的算數函式吧
-
ABS函式
ABS是計算絕對值的函式,簡單來說,絕對值的計算方法就是:0和正數的絕對值就是其本身,負數的絕對值就是去掉符號的結果
SELECT m,ABS(m) AS abs_col FROM 表名;
-
求餘MOD函式
MOD(被除數,除數),例如7/3的餘數是1,就是MOD(7 , 1)
SELECT m,n,MOD(m,n) AS mod_col FROM 表名;
-
ROUND--四捨五入
ROUND(物件數值,保留小數的位數)例如7.8888,保留一位,就是ROUND(7.8888 , 1)
SELECT m,n,ROUND(m,n) AS round_col FROM 表名;
-
字串函式
-
CONCAT 拼接
在實際業務中,我們會經常碰到abc + de = abcde這樣希望字串拼接的情況,通過兩條豎線"||"就可以實現
SELECT str1,str2,CONCAT(str1,str2) AS str_col FROM 表名;
-
LENGTH 字串的長度
LENGTH(字串)
SELECT str1,LENGTH(str1) AS len_str FROM 表名;
-
LOWER 小寫轉換
LOWER(字串)
SELECT str1,LOWER(str1) AS low_str FROM 表名;
-
SUBSTRING 字串的擷取
SUBSTRING(物件字串 FROM 擷取的起始位置 FOR 擷取的字元數)
SELECT str1,SUBSTRING(str1 FROM 3 FOR 2) AS sub_str FROM 表名;
-
UPPER 大寫轉換
UPPER(字串)
SELECT str1,UPPER(str1) AS up_str FROM 表名;
-
將空字串轉換為固定字元
SELECT COALESCE ( NULL, '你好' )
-
日期函式
-
CURRENT_DATE 當前日期,2018-12-21
SELECT CURRENT_DATE;
-
CURRENT_TIME 當前時間,22:52:57
SELECT CURRENT_TIME;
-
CURRENT_TIMESTAMP 當前日期和時間,2018-12-21 22:53:09
SELECT CURRENT_TIMESTAMP;
-
EXTPACT 擷取日期元素
EXTPACT(日期元素 FROM 日期)
SELECT CURRENT_TIMESTAMP
,
extract( YEAR FROM CURRENT_TIMESTAMP ) AS YEAR,
extract( MONTH FROM CURRENT_TIMESTAMP ) AS MONTH,
extract( DAY FROM CURRENT_TIMESTAMP ) AS DAY,
extract( HOUR FROM CURRENT_TIMESTAMP ) AS HOUR,
extract( MINUTE FROM CURRENT_TIMESTAMP ) AS MINUTE,
extract( SECOND FROM CURRENT_TIMESTAMP ) AS SECOND;
執行結果
CURRENT_TIMESTAMP | YEAR | MONTH | DAY | HOUR | MINUTE | SECOND |
---|---|---|---|---|---|---|
2018-12-21 23:00:06 | 2018 | 12 | 21 | 23 | 0 | 6 |
-
Date()函式 ,返回當前時間裡的日期部分
select DATE(CURRENT_TIMESTAMP);
-
常用日期和時間處理函式
函式 | 說明 |
---|---|
AddDate() | 增加一個日期(天,周等) |
AddTime() | 增加一個時間(時,分等) |
CurDate() | 返回當前日期 |
CurTime() | 返回當前時間 |
Date() | 返回當前日期時間的日期部分 |
DateDiff() | 計算兩個日期只差 |
Date_Add() | 高度靈活的日期運算函式 |
-
轉換函式
轉換這個詞的含義非常廣泛,在SQL中有兩層意思,一是資料型別轉換,簡稱為型別轉換,另一層意思是值得轉換
-
CAST函式
CAST(轉換前的值 AS 想要轉換的資料型別)
可以轉換的型別是有限制的。這個型別可以是以下值其中的一個:
- 二進位制,同帶binary字首的效果 : BINARY
- 字元型,可帶引數 : CHAR()
- 日期 : DATE
- 時間: TIME
- 日期時間型 : DATETIME
- 浮點數 : DECIMAL
- 整數 : SIGNED
- 無符號整數 : UNSIGNED
SELECT CAST('0001' AS SIGNED)
SELECT CAST('2018-1-4' AS date)
-
COALESCE -- 將NULL轉換為其他值
COALESCE(資料1,資料2....)
SELECT COALESCE(NULL,1) AS col_1 ,
COALESCE(NULL,NULL,'測試') AS col_2 ;
謂詞
-
什麼是謂詞
雖然之前沒有提及過謂詞這個概念,但其實前面已經使用過了,例如=,<.>等比較運算子,其正式名稱就是比較謂詞,將會給大家介紹一下幾個謂詞
- LIKE
- BETWEEN
- IS NULL , IS NOT NULL
- IN
- EXISTS
-
LIKE謂詞
LIKE這個關鍵字其實在實際應用中經常會用到,這就是模糊查詢
SELECT
*
FROM
shop
WHERE
name LIKE '%刀%'
這裡這個sql語句的意思就是說,只要name這個欄位裡面含有刀字的都會查出來
-
BETWEEN謂詞--範圍查詢
使用BETWEEN可以進行範圍查詢,比如說我們想查出年齡在18到20的人
SELECT
*
FROM
shop
WHERE
age BETWEEN 18 and 20
-
IS NULL 和 IS NOT NULL判斷是否為空
這裡前面都說過了,簡單的寫個sql語句
SELECT
*
FROM
shop
WHERE
name IS NOT NULL
-
IN謂詞--OR的簡便用法
我們之前用or查詢過查過商品是50元或者100元的商品
SELECT
*
FROM
shop
WHERE
jiage = 50
OR jiage = 10
如果隨著天劍的越來越多,一直追加OR嗎,當然是不可能的,這裡就要使用到IN謂詞了
SELECT
*
FROM
shop
WHERE
jiage IN ( 50, 10 )
這裡還有 NOT IN,意思和IN關鍵字相反
這裡需要對NOT IN進行說明下,NOT IN裡面是不能有NULL的,有空的話查詢的結果就是空,一條結果都不會出來
-
EXIST謂詞
EXIST位置的作用是判讀是否存在滿足條件的記錄,語法理解起來比較困難 這裡為了理解起來比較方便,有建立了一張商店商品表
商店(tenpo_id) | 商店名稱(tenpomei) | 商品編號(shopinid) | 數量(suryo) |
---|---|---|---|
000A | 北京 | 0001 | 50 |
000A | 北京 | 0002 | 50 |
000A | 北京 | 0003 | 50 |
000A | 北京 | 0004 | 50 |
這裡要查的條件就是查出北京店(000A)在售商品的銷售單價
SELECT shopin_mei,hanbai_tanka FROM Shopin AS S
WHERE EXISTS (SELECT * FROM Tenshopin AS TS WHERE tenpo_id = '000A' AND S.shopid_id = TS.shopinid)
執行結果
shopin_mei | hanbai_tanka |
---|---|
T恤衫 | 500 |
打孔器 | 320 |
運動T恤 | 2800 |
菜刀 | 2800 |
之前我們學的謂詞,基本上都是列LIKE字串或者列BETWEEN 值1AND值2,這樣指定引數,而EXIST的左側並沒有任何的引數,很奇妙吧,這是因為EXIST是隻有1個引數的謂詞,EXIST只需要在右邊書寫一個引數,該引數通常就是一個子查詢,就如我們上面所寫的那樣
CASE表示式
-
CASE表示式的語法
其實CASE表示式和java中的switch還是很像的,語法分為簡單CASE表示式和搜尋CASE表示式兩種,下來就來看看錶達式的語法吧
CASE
WHEN <判斷表示式> THEN <表示式>
WHEN <判斷表示式> THEN <表示式>
.
.
ELSE NULL
END
CASE表示式會對WHEN中的條件進行判斷,如果條件成立就輸出THEN裡的內容,如果沒有符合條件就輸出的是ELSE裡的內容,最終走向END,END是不能省略的
搜尋CASE表示式
SELECT
wwww,
CASE
WHEN jiage = 200 THEN CONCAT( 'A:', jiage )
WHEN jiage = 10 THEN CONCAT( 'B:', jiage )
ELSE NULL
END AS casejiage
FROM
shop
簡單CASE表示式
SELECT
wwww,
CASE jiage
WHEN 200 THEN CONCAT( 'A:', jiage )
WHEN 10 THEN CONCAT( 'B:', jiage )
ELSE NULL
END AS casejiage
FROM
shop
最後的ELSE NULL代表了上述條件都不成立時返回NULL,其實這個是可以省略的,預設的就是NULL
- 這裡我們對之前的GROUP BY進行下改造 之前我們通過GROUP BY分組查某個分類商品的總價,其實通過CASE表示式也是可以完成的,我們一起來看看吧
SELECT
SUM(CASE WHEN shopin_bunrui = '衣服' THEN hantai_tanka END) AS sum_tanka_ihuku,
SUM(CASE WHEN shopin_bunrui = '廚房用具' THEN hantai_tanka END) AS sum_tanka_kitchen
FROM Shopin
執行結果
sum_tanka_ihuku | sum_tanka_kitchen |
---|---|
5000 | 600 |
這樣的結果會以"行"的形式輸出,而無法以列的形式進行排列
第七章:結合運算
表的加減法
-
表的加法--UNION
學習之前我們先新增一張表,和之前的Shopin表的結構一樣,只是表面變成了Shipn2,在表中新增幾條資料
INSERT INTO `shopin2`(`shopin_id`, `shopin_mei`, `shopin_bunrui`, `hanbai_tanka`, `shiire_tanka`, `tprokubi`) VALUES ('0001', 'T恤衫', '衣服', 1000, 500, '2018-12-24');
INSERT INTO ``shopin2`(`shopin_id`, `shopin_mei`, `shopin_bunrui`, `hanbai_tanka`, `shiire_tanka`, `tprokubi`) VALUES ('0002', '打孔器', '辦公用品', 500, 320, '2018-12-12');
INSERT INTO `shopin2`(`shopin_id`, `shopin_mei`, `shopin_bunrui`, `hanbai_tanka`, `shiire_tanka`) VALUES ('0003', '運動T恤', '衣服', 4000, 2800);
INSERT INTO `shopin2`(`shopin_id`, `shopin_mei`, `shopin_bunrui`, `hanbai_tanka`, `shiire_tanka`) VALUES ('0009', '手套', '衣服', 800, 500);
INSERT INTO ``shopin2`(`shopin_id`, `shopin_mei`, `shopin_bunrui`, `hanbai_tanka`, `shiire_tanka`, `tprokubi`) VALUES ('0010', '水壺', '廚房用具', 2000, 1700, '2018-12-12');
這張表的有三條資料是和之前的表是重複的,有兩條是這張表獨有的,使用UNION對錶就行加法計算
SELECT shopin_id,shopin_mei
FROM Shopin
UNION
SELECT shopin_id,shopin_mei
FROM Shopin2
執行結果我就不展示了,做了實驗了小夥伴應該會發現,只查出了10調資料,是沒有重複資料的,因為0001~0003的資料兩個表都存在,這就是我們在學校學過的並集運算
-
包含重複行的集合運算--ALL選項
SELECT shopin_id,shopin_mei
FROM Shopin
UNION ALL
SELECT shopin_id,shopin_mei
FROM Shopin2
在集合中使用ALL選項,可以保留重複行
-
集合運算的注意事項
- 作為運算物件的記錄列數必須相同,像下面的例子,一個是查兩列,一個是查三列,會發生錯誤,無法進行計算
SELECT shopin_id,shopin_mei
FROM Shopin
UNION
SELECT shopin_id,shopin_mei,hanbai_tanka
FROM Shopin2
- 作為運算物件的記錄中列的型別必須一致,從左側開始,相同位置上的列必須是同一資料型別,例如,下面的SQL語句中,第二列的資料型別不一致,一個是數值型別,一個是日期型別 ,所以就會發生錯誤
SELECT shopin_id,hanbai_tanka
FROM Shopin
UNION
SELECT shopin_id,torokubi
FROM Shopin2
- 可以使用任何SELECT語句,但ORDER BY子句只能在最後使用一次
通過UNION進行並集運算時可以使用任何形式的SELECT語句,之前學過的WHERE,GROUP BY,HAVING等子句都可以使用,但是ORDER BY只能在最後使用一次
SELECT shopin_id,shopin_mei
FROM Shopin
UNION
SELECT shopin_id,shopin_mei
FROM Shopin2
ORDER BY shopin_id;
-
選取表中公共部分--INTERSECT
下面介紹就是我們數學運算中的交集,就是兩張表都共同存在的資料,和UNION語法完全一樣
mysql裡是錯的
SELECT shopin_id,shopin_mei
FROM Shopin
INTERSECT
SELECT shopin_id,shopin_mei
FROM Shopin2
我在做實驗的時候,其實mysql並沒有這個關鍵字,這種語法在mysql裡是錯的,但是,也可以通過一些別的方法實現去取的交集
SELECT
shopin_id,
shopin_mei
FROM Shopin
UNION
SELECT
shopin_id,
shopin_mei
FROM Shopin2
GROUP BY
shopin_id,
shopin_mei
HAVING
COUNT( shopin_id ) =2
聯結(以列為單位進行聯結)
-
什麼是聯結
通俗來說,就是進行這些集合運算時,會導致記錄行數的增減,使用UNION會增加記錄行數,但是這些運算並不會導致列數改變,作為集合運算物件表的前提就是列數要一致,因此運算結果不會導致列的增加
本次學習的聯結(JOIN)運算,簡單來說就是將其他表中的列新增過來,進行新增列的運算,該操作通常用於無法從一張表中獲取期望資料(列)的情況,實際應用中,期望得到的資料往往會分散在不同的表中,使用聯結就可以從不同的表中選取資料了
-
內聯結--INNER JOIN
- 商品表(Shopin)
商品編號 | 商品名稱 | 商品分類 | 銷售單價 | 進貨單價 | 登記日期 |
---|---|---|---|---|---|
0001 | T恤衫 | 衣服 | 1000 | 500 | 2018-12-24 |
0002 | 打孔器 | 辦公用品 | 500 | 320 | 2018-12-12 |
0003 | 運動T恤 | 衣服 | 4000 | 2800 | |
0004 | 菜刀 | 廚房用具 | 3000 | 2800 | 2018-12-24 |
0005 | 高壓鍋 | 廚房用具 | 6800 | 5000 | 2018-06-24 |
0006 | 叉子 | 廚房用具 | 500 | 2018-12-24 | |
0007 | 擦菜板 | 廚房用具 | 880 | 790 | 2018-04-01 |
0008 | 圓珠筆 | 辦公用品 | 100 | 2018-10-01 |
- 商店商品表(TenpoShoin)
商店(tenpo_id) | 商店名稱(tenpomei) | 商品編號(shopinid) | 數量(suryo) |
---|---|---|---|
000A | 北京商店雜貨鋪 | 0001 | 50 |
000A | 北京商店雜貨鋪 | 0002 | 50 |
000A | 北京商店雜貨鋪 | 0003 | 50 |
000A | 北京商店雜貨鋪 | 0004 | 50 |
000B | 南京商店雜貨鋪 | 0004 | 50 |
000C | 上海商店雜貨鋪 | 0004 | 50 |
從上面兩張表裡,我們發現都存在有相同的列--商品編號,
所謂聯結運算,就是以商品編號為橋樑,將滿足條件的彙集到同一結果之中,比如,我們想從Shopin表中取出商品名稱(shopin_mei)和銷售單價(hanbai_tanka),與TenpoShopin表中的內容進行結合
執行結果,只寫了一條,剩下的都省略了
tenpo_id | tenpomei | shopinid | shopin_mei | hanbai_tanka |
---|---|---|---|---|
000A |