Mysql基礎總結(部分參照燕十八老師的教學)
1. 什么是SQL(Structured Query Language)結構查詢陳述句
SQL陳述句是一種what型語言【想要什么,給你】,語法相對簡單易懂
-
SQL語言的劃分- DDL
(Data Definition Language)-資料庫定義語言;用來定義資料庫物件、資料表和列;使用DDL創建、洗掉、修改資料庫的表和結構 - DML
(Data Manipulation Language)-資料庫操作語言;操作資料庫的相關資料,比如增加、洗掉、修改表中的資料 - DCL
(Data Control Language)-資料控制語言;用它來定義訪問權限和安全等級 - DQL
(Data Query Language)-資料查詢語言;資料查詢語言,用來查詢資料
- DDL
-
SQL陳述句的執行順序select distinct player_id , player_name , count(*) as num # 順序5 from player join team on player.team_id = team.team_id # 順序1 where height > 1.80 # 順序2 group by player.team_id # 順序3 having num >2 # 順序4 order by num desc # 順序6 limit 2; # 順序7- 完整的順序是
from子句組裝資料(包括join)where子句進行條件篩選group by分組- 使用聚集函式進行計算、資料映射
having篩選分組- 計算所有的運算式
select的欄位order by排序limit篩選
- 完整的順序是
-
SQL陳述句的執行流程? Mysql中的流程:SQL陳述句 → 快取查詢 → 決議器 → 優化器 → 執行器

-
查詢快取:Server如何在查詢快取總發現了這條SQL陳述句,就會直接將結果回傳給客戶端;如果沒有,就進入到決議器階段,需要說明的是,因為查詢快取往往效率不高,所以在Mysql 8.0 之后就拋棄了這個功能,
-
決議器:在決議器中隊SQL陳述句進行語法分析、語意分析
-
優化器:在優化器中會確定SQL陳述句的執行路徑,比如是根據全表檢索,還是根據索引來檢驗等
-
執行器:在執行之前需要判斷改用戶是否具備權限,如果具備權限就執行SQL查詢并回傳結果,在Mysql 8.0以下的版本,如果設定了查詢快取,這時會將查詢結果進行快取,
-
2. Mysql 架構
- Mysql是Client/Server架構,體系架構圖如下

- 由以下幾個部分組成
- 連接池組件(Connection Pool)
- 管理服務和工具組件(Enterprise Management Services & Utilities)
- SQL 介面組件(SQL Interface)
- 查詢分析器(Parser)
- 優化器組件(Optimizer)
- 緩沖組件(Cache & Buffer)
- 插件式儲存引擎(Pluggable Storage Engines)
- 物理檔案(File System , Files & Logs)
-
關于儲存引擎
-
InnoDB儲存引擎Mysql 5.5 版本后默認的儲存引擎,優點是支持事務、行級鎖、外鍵約束、支持崩潰后的安全恢復
-
Myisam儲存引擎不支持事務和外鍵,支持全文索引(只對英文有效),特點是查詢速度快
-
Memory儲存引擎資料放在記憶體當中(類似
memcache)以便得到更快的回應速度,但是崩掉的話資料會丟失 -
NDB儲存引擎主要用于Mysql Cluster 分布式集群
-
Archive儲存引擎有很好的壓碩訓制,用于檔案檔案,寫入時會進行壓縮
-
3. 常用庫/表操作陳述句
1. mysql -h localhost -u root -p # 以root用戶連接本地資料庫
2. show databases; # 查看Mysql服務中的所有資料庫
3. create database database_name; # 創建資料庫
4. use databases; # 更改操作的資料庫物件
5. \c # 取消執行當前未輸入mysql陳述句
6. show tables; # 查看該操作資料庫物件中所有的資料表名和視圖名
7. desc table_name/view_name; # 查看表/視圖結構
8. truncate table_name; # 清空表資料【表結構不變】
9. delete from table_name; # 洗掉表
10. show create table table_name; # 查看建表/視圖程序
11. show table status \G; # 查看資料庫中的所有表資訊;\G 豎行顯示
12. show table status where name = table_name \G; # 指定表
13. rename table_name; # 改表名
14. drop table/view table_name/view_name; # 洗掉表/視圖
4. 增刪改查
1.insert
insert into table_name (column1,column2 ……) values (value1,value2 ……);
2.delete
delete from table_name where …… ; # where表示指定條件,不用where將針對表整表操作
3.update
update table_name set column1 = new_value , column2 = new_value …… where ……;
4. select
select cloumn1,cloumn2…… from table_name where …… group by …… having …… order by …… limit …… ;
# where|group by|having|order by|limit 可以沒有其中某些項,若有必須按照先后順序
5.深入理解select
select 是增刪改查的重點,也是難點,能否寫出高性能的sql陳述句,select是否熟練占很大一部分
-
列是變數,變數就可以進行各種運算,包括算術運算、邏輯運算 等
-
where后面的陳述句是運算式,運算式的值為真或假 eg:where 1則恒為真 查詢整張表,反之where 0恒位假 查詢結果位Empty -
select 陳述句還可以配合算術運算子、邏輯運算子、位運算子以及相關函式寫出更高性能的查詢陳述句
-
常用的
select用法以goods表為例-
數字篩選
select goods_id,goods_name,shop_price from goods where shop_price > 300; -
字符篩選
select goods_id,goods_name,shop_price from goods where goods_name = 'kd876'; -
區間篩選
select goods_id,goods_name,shop_price from goods where shop_price between 300 and 3000; -
多條件篩選
select goods_id,goods_name,shop_price from goods where shop_price between 300 and 3000 and goods_id > 10 ; -
模糊條件篩選
select goods_id,goods_name,shop_price from goods where goods_name like '諾基亞%'; # 通配符% 表示任意多個字符 _ 表示任意單個字符 -
在字串組里篩選
select goods_id,goods_name,shop_price from goods where goods_id in (3,10); # goods_id in(3,10)等價于goods_id = 3 or goods_id = 10 -
借助函式優化篩選
select goods_id,goods_name,shop_price from goods where left(goods_name,2)='kd'; # 函式left(a,n)表示在a字串中從左到右取n個字符 -
全字符段篩選
select * from goods; -
不重復篩選
select distinct goods_id,goods_name,shop_price from goods; # distinct 不重復的意思 -
排序篩選
select goods_id,goods_name,shop_price from goods where shop_price >300 order by shop_price desc; # asc升序(默認)/ desc 降序
-
-
-
補上后續練習所需要的表格代碼
create table goods ( goods_id mediumint(8) unsigned primary key auto_increment, goods_name varchar(120) not null default '', cat_id smallint(5) unsigned not null default '0', brand_id smallint(5) unsigned not null default '0', goods_sn char(15) not null default '', goods_number smallint(5) unsigned not null default '0', shop_price decimal(10,2) unsigned not null default '0.00', market_price decimal(10,2) unsigned not null default '0.00', click_count int(10) unsigned not null default '0' ) engine=InnoDB default charset=utf8; insert into `goods` values (1,'kd876',4,8,'ecs000000',1,1388.00,1665.60,9), (4,'諾基亞n85原裝充電器',8,1,'ecs000004',17,58.00,69.60,0), (3,'諾基亞原裝5800耳機',8,1,'ecs000002',24,68.00,81.60,3), (5,'索愛原裝m2卡讀卡器',11,7,'ecs000005',8,20.00,24.00,3), (6,'勝創kingmax記憶體卡',11,0,'ecs000006',15,42.00,50.40,0), (7,'諾基亞n85原裝立體聲耳機hs-82',8,1,'ecs000007',20,100.00,120.00,0), (8,'飛利浦9@9v',3,4,'ecs000008',1,399.00,478.79,10), (9,'諾基亞e66',3,1,'ecs000009',4,2298.00,2757.60,20), (10,'索愛c702c',3,7,'ecs000010',7,1328.00,1593.60,11), (11,'索愛c702c',3,7,'ecs000011',1,1300.00,0.00,0), (12,'摩托羅拉a810',3,2,'ecs000012',8,983.00,1179.60,13), (13,'諾基亞5320 xpressmusic',3,1,'ecs000013',8,1311.00,1573.20,13), (14,'諾基亞5800xm',4,1,'ecs000014',1,2625.00,3150.00,6), (15,'摩托羅拉a810',3,2,'ecs000015',3,788.00,945.60,8), (16,'恒基偉業g101',2,11,'ecs000016',0,823.33,988.00,3), (17,'夏新n7',3,5,'ecs000017',1,2300.00,2760.00,2), (18,'夏新t5',4,5,'ecs000018',1,2878.00,3453.60,0), (19,'三星sgh-f258',3,6,'ecs000019',12,858.00,1029.60,7), (20,'三星bc01',3,6,'ecs000020',12,280.00,336.00,14), (21,'金立 a30',3,10,'ecs000021',40,2000.00,2400.00,4), (22,'多普達touch hd',3,3,'ecs000022',1,5999.00,7198.80,16), (23,'諾基亞n96',5,1,'ecs000023',8,3700.00,4440.00,17), (24,'p806',3,9,'ecs000024',100,2000.00,2400.00,35), (25,'小靈通/固話50元充值卡',13,0,'ecs000025',2,48.00,57.59,0), (26,'小靈通/固話20元充值卡',13,0,'ecs000026',2,19.00,22.80,0), (27,'聯通100元充值卡',15,0,'ecs000027',2,95.00,100.00,0), (28,'聯通50元充值卡',15,0,'ecs000028',0,45.00,50.00,0), (29,'移動100元充值卡',14,0,'ecs000029',0,90.00,0.00,0), (30,'移動20元充值卡',14,0,'ecs000030',9,18.00,21.00,1), (31,'摩托羅拉e8 ',3,2,'ecs000031',1,1337.00,1604.39,5), (32,'諾基亞n85',3,1,'ecs000032',4,3010.00,3612.00,9); create table category ( cat_id smallint unsigned auto_increment primary key, cat_name varchar(90) not null default '', parent_id smallint unsigned )engine=InnoDB charset utf8; INSERT INTO `category` VALUES (1,'手機型別',0), (2,'CDMA手機',1), (3,'GSM手機',1), (4,'3G手機',1), (5,'雙模手機',1), (6,'手機配件',0), (7,'充電器',6), (8,'耳機',6), (9,'電池',6), (11,'讀卡器和記憶體卡',6), (12,'充值卡',0), (13,'小靈通/固話充值卡',12), (14,'移動手機充值卡',12), (15,'聯通手機充值卡',12); CREATE TABLE `result` ( `name` varchar(20) DEFAULT NULL, `subject` varchar(20) DEFAULT NULL, `score` tinyint(4) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; insert into result values ('張三','數學',90), ('張三','語文',50), ('張三','地理',40), ('李四','語文',55), ('李四','政治',45), ('王五','政治',30); create table a ( id char(1), num int )engine=InnoDB charset utf8; insert into a values ('a',5),('b',10),('c',15),('d',10); create table b ( id char(1), num int )engine=InnoDB charset utf8; insert into b values ('b',5),('c',15),('d',20),('e',99); create table m( mid int, hid int, gid int, mres varchar(10), matime date )engine=InnoDB charset utf8; insert into m values (1,1,2,'2:0','2006-05-21'), (2,2,3,'1:2','2006-06-21'), (3,3,1,'2:5','2006-06-25'), (4,2,1,'3:2','2006-07-21'); create table t ( tid int, tname varchar(20) )engine=InnoDB charset utf8; insert into t values (1,'國安'), (2,'申花'), (3,'布爾聯隊'); create table mian ( num int) engine=InnoDB; insert into mian values (3), (12), (15), (25), (23), (29), (34), (37), (32); create table user ( uid int primary key auto_increment, name varchar(20) not null default '', age smallint unsigned not null default 0 ) engine=InnoDB charset utf8; create table boy ( hid char(1), bname varchar(20) )engine=InnoDB charset utf8; insert into boy (bname,hid) values ('屌絲','A'), ('楊過','B'), ('陳冠希','C'); create table girl ( hid char(1), gname varchar(20) )engine=InnoDB charset utf8; insert into girl(gname,hid) values ('小龍女','B'), ('張柏芝','C'), ('死宅女','D');? 注:上述包含的表格有
goods、category、result、a、b、m、t、mian、user、boy、girl
?
6.查詢練習以goods表為例
-
查詢出名字為’諾基亞NXX’的手機
select * from goods where goods_id in(4,11); -
查詢出名字不以’諾基亞’開頭的商品
select * from goods where goods_name not like '諾基亞%'; -
查詢出第4和第11行的所有資訊
-
把
goods表中商品名為’諾基亞xxxx’改為’HTCxxxx’select goods_id, concat('HTC',substring(goods_name,4)) from goods where goods_name like '諾基亞%'; # 1. 函式concat(a,b) 將ab兩個字串連接成一個字串 # 2. 函式substring(string,position)從特定位置開始的字串回傳一個給定長度的子字串
- 小結:當涉及到多重條件查詢需要用到運算子、and、or、not……之類來修飾條件時
* 一定要先弄清楚條件之間的分類
* 使用( )將其分類,避免優先級之類的問題
- 面試題mian表
將mian表中處于[20,29]之間的num值改成20,[30,39]之間的num值改成30,一句sql完成,

update mian set num = (floor(num/10)*10) where num between 20 an 39; # 函式floor(x) 取不大于x的最大整數值
7. group by 分組與統計函式
-
常用統計函式
max() # 獲取最大值 min() # 獲取最小值 avg() # 求取平均值 sum() # 求和 count() # 計算行數/條數 *特別注意count()回傳的是一個總行數 distinct() # 求有多少種不同解 -
另外注意:當出現
group by分組種不能配對的情況,該欄位取查詢時候第一次出現的值
8. having 篩選結果集
注:having 并不一定 與 where共存(這種情況可以看做類似where 1這種陳述句可以忽略),但一定在where之后;可以存在只有having而沒有where的情況
-
查詢
goods表中商品比市場價低出多少?select goods_id ,goods_name,market_price - shop_price from goods ; -
查詢
goods表中商品比市場價低出至少200元的商品select goods_id ,goods_name,(market_price - shop_price) as discount from goods where market_price - shop_price ; # 注意為什么where后面不能用 discountselect goods_id,goods_name,(market_price-shop_price) as discount from goods having discount>200;
9. where __ group by __ having 綜合練習result表

- 有以上
result表,要求查詢出2門及2門以上不及格的平均成績 ※※※經典題目※※※- 難點分析:如何找出2門及2門以上不及格的同學
-
一種典型錯誤 ? 【錯誤點:對count和比較運算兩者結合的理解錯誤】
msyql> select name , count(score<60) as gks , avg(score) as pjf from result group by name having gks >= 2; +--------+-----+---------+ | name | gks | pjf | +--------+-----+---------+ | 張三 | 3 | 60.0000 | | 李四 | 2 | 50.0000 | +--------+-----+---------+ 2 rows in set (0.00 sec) # 貌似是正確的,但只針對此種情況驗證:假如增加1行資料
values('趙六','語文',88),('趙六','數學',99),('趙六','物理',100)再次執行上面的
sql陳述句,將會得到如下結果+--------+-----+---------+ | name | gks | pjf | +--------+-----+---------+ | 張三 | 3 | 60.0000 | | 李四 | 2 | 50.0000 | | 趙六 | 3 | 95.6667 | +--------+-----+---------+ 3 rows in set (0.00 sec) # 很明顯有語意上的錯誤!實際上count(score)和count(score<60)查詢出的結果是一樣的,函式count()回傳的是總行數! -
正確解題思路?(逆向思維)
1. select name ,avg(score),as pjf from result group by name; +--------+---------+ | name | pjf | +--------+---------+ | 張三 | 60.0000 | | 李四 | 50.0000 | | 王五 | 30.0000 | | 趙六 | 95.6667 | +--------+---------+ 4 rows in set (0.00 sec) # 1. 查詢出所有同學的平均分,并分組2. select name, score<60 from result; +--------+----------+ | name | score<60 | +--------+----------+ | 張三 | 0 | | 張三 | 1 | | 張三 | 1 | | 李四 | 1 | | 李四 | 1 | | 王五 | 1 | | 趙六 | 0 | | 趙六 | 0 | | 趙六 | 0 | +--------+----------+ 9 rows in set (0.00 sec) # 2. 查看每個同學的掛科情況;這里運用了邏輯運算,這個點也很重要!score<60 若真則回傳0 若假則回傳13. select name , sum(score<60) as gks from result group by name; +--------+------+ | name | gks | +--------+------+ | 張三 | 2 | | 李四 | 2 | | 王五 | 1 | | 趙六 | 0 | +--------+------+ 4 rows in set (0.00 sec) # 3. 計算每位同學的總掛科數4. select name ,sum(score<60) as gks ,avg(score) as pjf from result group by name having gks >=2; +--------+------+------------+ | name | gks | pjf | +--------+------+------------+ | 張三 | 2 | 60.0000 | | 李四 | 2 | 50.0000 | +--------+------+------------+ 2 rows in set (0.00 sec) # 4. 整合1.3步,得到結果集,并篩選出gks大于等于2的同學
10. order by 排序(在記憶體中排序)與limit(限制范圍)綜合查詢goods表
-
按欄目由低到高排序,欄目內部按價格由高到低排序
select goods_id ,goods_name ,shop_price ,cat_id from goods order by cat_id desc,shop_price asc; -
取出價格最高的前3名商品
select goods_id ,goods_name,shop_price from goods order by shop_price desc limit 0,3; # limit x,y 其中x代表起始位置也就是偏移量,y代表回傳最大行數;x初始值為0 -
取出商品市場價前10到25的商品資訊
select goods_id ,goods_name,market_price from goods order by market_price limit 11,15;
11. 子查詢
mysql子查詢是嵌套在另一個查詢(如select、insert、update或者delete)中的查詢,這里重點總結了嵌套在select中的子查詢
- where 子查詢【以內層查詢結果通常為變數作為外層查詢的比較條件】
- 如何查詢每個欄目下面最新的那件產品?
- 語意決議:欄目列 :
cat_id;最新的那件產品?goods_id為最大值時所對應的那一件產品
- 語意決議:欄目列 :
# 1. 陷阱演示 ?
# 思路:最新的商品 max(goods_id);每個欄目 group by cat_id
select max(goods_id) ,goods_name ,cat_id ,shop_price from goods group by cat_id ;
# 報錯:ERROR 1055 (42000): Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated
# column 'zion.goods.goods_name' which is not functionally dependent on columns in GROUP BY clause;
# this is incompatible with sql_mode=only_full_group_by 大概意思是 語意缺陷,不兼容
#分析:”先查詢再排序“ group by cat_id 但是goods_name,shop_price應該取誰的呢?
# 2. 正確方法 ?
# 思路:”先排序再查詢“ 需要用到子查詢/連接查詢
# ”先排序“
select max(goods_id),cat_id from goods group by cat_id;
+---------------+--------+
| max(goods_id) | cat_id |
+---------------+--------+
| 16 | 2 |
| 32 | 3 |
| 18 | 4 |
| 23 | 5 |
| 7 | 8 |
| 6 | 11 |
| 26 | 13 |
| 30 | 14 |
| 28 | 15 |
+---------------+--------+
9 rows in set (0.00 sec)
# ”再查詢“
select cat_id ,goods_id, goods_name, shop_price from goods where goods_id in (select max(goods_id) from goods group by cat_id);
+--------+----------+----------------------------------------+------------+
| cat_id | goods_id | goods_name | shop_price |
+--------+----------+----------------------------------------+------------+
| 11 | 6 | 勝創kingmax記憶體卡 | 42.00 |
| 8 | 7 | 諾基亞n85原裝立體聲耳機hs-82 | 100.00 |
| 2 | 16 | 恒基偉業g101 | 823.33 |
| 4 | 18 | 夏新t5 | 2878.00 |
| 5 | 23 | 諾基亞n96 | 3700.00 |
| 13 | 26 | 小靈通/固話20元充值卡 | 19.00 |
| 15 | 28 | 聯通50元充值卡 | 45.00 |
| 14 | 30 | 移動20元充值卡 | 18.00 |
| 3 | 32 | 諾基亞n85 | 3010.00 |
+--------+----------+----------------------------------------+------------+
9 rows in set (0.00 sec)
# 分析:1.由此可見 select max(goods_id) ,goods_name ,shop_price from goods 除了goods_id符合題意,其它的在語意上就是存在缺陷的;
# 這是一個有缺陷的陳述句,
# 2.列就是變數;把查詢這個變數(列)的sql陳述句作為外層sql陳述句的比較條件,這么做的目的是為了我們每次更新商品后,都能取得最新的那個商品,
# 這樣也不會出現 列與列不匹配錯亂的情況
-
查詢出編號位19的商品的欄目名稱[欄目名稱放在
category表中]select cat_id,cat_name from category where cat_id = ( select cat_id from goods where goods_id = 19 ); +--------+-----------+ | cat_id | cat_name | +--------+-----------+ | 3 | GSM手機 | +--------+-----------+ 1 row in set (0.00 sec)
- from 子查詢 【將查詢出來的結果當成一個新”表“來操作】
==============未完待續……
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/243519.html
標籤:MySQL
上一篇:高性能MySQL學習總結二----常見資料型別選擇及優化
下一篇:ashtop學習分享
