SQL應用
一、client
mysql> help
? (\?) Synonym for `help'.
clear (\c) Clear the current input statement.
connect (\r) Reconnect to the server. Optional arguments are db and host.
delimiter (\d) Set statement delimiter.
edit (\e) Edit command with $EDITOR.
ego (\G) Send command to mysql server, display result vertically.
exit (\q) Exit mysql. Same as quit.
go (\g) Send command to mysql server.
help (\h) Display this help.
nopager (\n) Disable pager, print to stdout.
notee (\t) Don't write into outfile.
pager (\P) Set PAGER [to_pager]. Print the query results via PAGER.
print (\p) Print current command.
prompt (\R) Change your mysql prompt.
quit (\q) Quit mysql.
rehash (\#) Rebuild completion hash.
source (\.) Execute an SQL script file. Takes a file name as an argument.
status (\s) Get status information from the server.
system (\!) Execute a system shell command.
tee (\T) Set outfile [to_outfile]. Append everything into given outfile.
use (\u) Use another database. Takes database name as argument.
charset (\C) Switch to another charset. Might be needed for processing binlog with multi-byte charsets.
warnings (\W) Show warnings after every statement.
nowarning (\w) Don't show warnings after every statement.
resetconnection(\x) Clean session context.
常用
\? 和'help'命令相同
\c 阻止上個命令運行
\G 格式化輸出(逐行輸出,針對列特別多的場景)
\q 退出會話(ctrl+d)
\. source 導入SQL腳本,類似於<
\! 調用linux命令
二、server
linux當中一切皆命令,一切皆文件。
mysql一切皆SQL,一切皆庫、表。
1、DDL
數據定義語言
1)庫定義
庫名,庫屬性
建庫
create database 庫名 charset utf8mb4 collate utf8mb4_bin;
數據庫名 字符集 排序規則
建庫規范:
1.庫名不能有大寫字母 #多平台兼容問題
2.建庫要加字符集
3.庫名不能有數字開頭
4.庫名要和業務相關
5.庫名不要太長
6.不要使用內置字符
create database xiaowu;
show create database xiaowu; #查看建庫的基本命令(建庫語句)
查庫(DQL)
show databases;
show create database xiaowu; #查看建庫的基本命令(建庫語句)
修改庫
show create database school;
alter database xiaowu charset utf8;
注意:修改字符集,修改后的字符集一定是原字符集的嚴格超集
只能改庫屬性,不能改庫名。
刪庫
生產中謹慎使用
mysql> drop database xiaowu;
2)表定義
創建表
create table stu(
列1 屬性(數據類型、約束、其他屬性) ,
列2 屬性,
列3 屬性
)
USE school;
CREATE TABLE stu(
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '學號',
sname VARCHAR(255) NOT NULL COMMENT '姓名',
sage TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '年齡',
sgender ENUM('m','f','n') NOT NULL DEFAULT 'n' COMMENT '性別' ,
sfz CHAR(18) NOT NULL UNIQUE COMMENT '身份證',
intime TIMESTAMP NOT NULL DEFAULT NOW() COMMENT '入學時間'
) ENGINE=INNODB CHARSET=utf8mb4 COMMENT '學生表';
列名 | 數據類型 | 長度 | 默認 | 主鍵 | 非空 | 無符號 | 自增 | 列值不重復 | 注釋 |
---|---|---|---|---|---|---|---|---|---|
id | int | PRIMARY KEY | NOT NULL | AUTO_INCREMENT | COMMENT '學號' | ||||
name | varchar | 255 | NOT NULL | COMMENT '姓名' | |||||
age | tinyint | DEFAULT 0 | NOT NULL | UNSIGNED | COMMENT '年齡' | ||||
gender | ENUM('m','f','n') | DEFAULT 'n' | NOT NULL | COMMENT '性別' | |||||
sfz | CHAR | 18 | NOT NULL | UNIQUE | COMMENT '身份證' | ||||
intinme | TIMESTAMP | DEFAULT NOW() | NOT NULL | COMMENT '入學時間' |
ENGINE=INNODB CHARSET=utf8mb4 COMMENT '學生表'
存儲引擎 字符集 注釋
建表規范:
1. 表名小寫 #多平台兼容問題
2. 不能是數字開頭
3. 注意字符集和存儲引擎
4. 表名和業務有關
5. 選擇合適的數據類型 #合適,簡短,足夠
6. 每個列都要有注釋
7. 每個列設置為非空,無法保證非空,默認值或用0來填充。
8. 必須要有主鍵
9. 列名不要太長
練習:
1、表名過長
2、id bigint(20)過大
3、數字列應該用數字類型
4、distribution_cost應該使用小數
5、時間列應該datatime類型
6、is_deleted用枚舉類型
查詢表(DQL)
mysql> show tables;
mysql> desc wp_users;
mysql> show create table stu;
修改表
例子:
1.在stu表中添加手機列
ALTER TABLE stu ADD shouji bigint NOT NULL UNIQUE KEy COMMENT '手機號';
alter table stu add shouji bigint notnull unique key comment '手機號' first ; #列首添加
alter table stu add shouji bigint notnull unique key comment '手機號' after id ; #在id列后添加一個列
2.手機列修改數據類型為char(11) modefy
alter table stu modify shouji char(11) not null unique key comment '手機號';
alter table stu rename t2; 改表名
3.刪除手機號列(危險操作)
mysql> alter table stu drop shouji;
刪除表、庫
mysql> drop table stu;
mysql> drop database 庫名;
3)DDL擴充
1、創建一張表
create table 庫名.表名(
列名 數據類型 約束 屬性,
列名 數據類型 約束 屬性,
列名 數據類型 約束 屬性,
...
)engine(引擎)=innodb charset(字符集)=utf8mb4;
2、線上DDL(alter)操作對於生產的影響
說明:在MySQL中,DDL語句在對表進行操作是,是要鎖“元數據表”的。
擴展:元數據是什么? ---》類似linux inode信息
在MySQL中,DDL語句對表進行操作時,是要鎖“元數據表”的,此時,所有修改類命令無法正常運行。所以在對於大表、業務繁忙的表,進行先上DDL操作時,要謹慎。盡量避開業務繁忙時間,進行DDL操作。
面試題回答要點:
1.SQL語句的意思是什么
以上四條語句是進行DDL加列操作
2.以上操作帶來的影響
在MySQL中,DDL語句對表進行操作時,是要鎖“元數據表”的,此時,所有修改類命令無法正常運行。所以在對於大表、業務繁忙的表,進行先上DDL操作時,要謹慎。盡量避開業務繁忙時間,進行DDL操作。
3.我們的建議:
(1)盡量避開業務繁忙時間,進行DDL。走流程
(2)建議使用:pt-online-schema-change(pt-osc) gh-ost工具進行DDL操作,減少鎖表影響
(3)如果8.0版本,可以不適用pt工具,8.0之前需要借助以上工具
2、DCL
數據控制語言
grant 授權
revoke 回收權限
權限管理的操作:
語法:
8.0之前:
grant 權限 on 對象 to 用戶 identified by '密碼';
grant 權限1,權限2,權限3... on 對象 to 用戶 identified by '密碼';
8.0之后:
create user 用戶 identified by '密碼';
grant 權限 on 對象 to 用戶;
grant 權限1,權限2,權限3... on 對象 to 用戶;
權限:
ALL:SELECT,INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE
ALL #以上所有權限,一般是管理員才擁有的
權限1,權限2,權限3... #普通用戶
grant option #超級管理員,給別的用戶授權
grant 權限1,權限2,權限3... on 對象 to 用戶 with grant option;
注意:不要隨意授權grant option,不然該用戶可以在服務器中為所欲為,包括刪除自帶的超級管理員(root@localhost)
對象: 庫、表(作用范圍)
*.* #所有庫所有表,一般是對管理員
wordpress.* #wordpress庫下所有表,開發和應用用戶,
wordpress.t1 #wordpress庫下t1表
MySQL授權表:
user #用戶對mysql服務的權限
db #用戶對某個庫的權限
tables_priv #用戶對某個表的權限
columns_priv #用戶對某列的權限
查詢所有用戶對mysql服務的權限
select * from mysql.user\G
查詢所有用戶對庫的權限
select * from mysql.db\G
查詢所有用戶對某個表的權限
select * from mysql.tables_priv\G
查詢所有用戶對某列的權限
select * from mysql.columns_priv\G
練習
需求1:創建管理員用戶,windows機器的navicat登錄到linux中的MySQL
mysql> grant all on *.* to root@'10.0.0.%' identified by '123' with grant option;
查詢創建的用戶:
mysql> select user,host,authentication_string from mysql.user;
查詢某個用戶的權限:
mysql> show grants for root@'10.0.0.%';
+--------------------------------------------------------------------+
| Grants for root@10.0.0.% |
+--------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'root'@'10.0.0.%' WITH GRANT OPTION |
+--------------------------------------------------------------------+
查詢所有用戶對mysql服務的權限
select * from mysql.user\G
查詢所有用戶對庫的權限
select * from mysql.db\G
查詢所有用戶對某個表的權限
select * from mysql.tables_priv\G
查詢所有用戶對某列的權限
select * from mysql.columns_priv\G
需求2:創建一個應用用戶app用戶,能從windows上登錄mysql,能夠對app庫下所有對象進行create,select,update,delete,insert操作
mysql> grant create,update,select,insert,delete on app.* to app@'10.0.0.%' identified by '123';
mysql> show grants for app@'10.0.0.%';
+-----------------------------------------------------------------------------+
| Grants for app@10.0.0.% |
+-----------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'app'@'10.0.0.%' |
| GRANT SELECT, INSERT, UPDATE, DELETE, CREATE ON `app`.* TO 'app'@'10.0.0.%' |
+-----------------------------------------------------------------------------+
2 rows in set (0.00 sec)
回收權限
linux:
chmod -R 644 /data ----> chmod -R 755 /data
MySQL:
MySQL中不能通過重復授權,修改權限,只能通過回收權限的方式進行修改
回收'app'@'10.0.0.%'對app庫的create權限
revoke create on app.* from 'app'@'10.0.0.%';
添加'app'@'10.0.0.%'對app庫的create權限
grant create on app.* to app@'10.0.0.%';
3、DML
數據操作語言
作用:對表中的數據進行增、刪、改
insert
--- 最標准的insert語句
mysql> desc stu; #先看看有什么列
mysql> insert into stu(id,sname,sage,sgender,sfz,intime)
-> values
-> (1,'zs',18,'m','123456',now());
mysql> select * from stu;
+----+-------+------+---------+--------+---------------------+
| id | sname | sage | sgender | sfz | intime |
+----+-------+------+---------+--------+---------------------+
| 1 | zs | 18 | m | 123456 | 2021-02-28 15:27:03 |
+----+-------+------+---------+--------+---------------------+
--- 省事的寫法
mysql> insert into stu
-> values
-> (2,'ls',18,'m','1234567',now());
mysql> select * from stu;
+----+-------+------+---------+---------+---------------------+
| id | sname | sage | sgender | sfz | intime |
+----+-------+------+---------+---------+---------------------+
| 1 | zs | 18 | m | 123456 | 2021-02-28 15:27:03 |
| 2 | ls | 18 | m | 1234567 | 2021-02-28 15:30:45 |
+----+-------+------+---------+---------+---------------------+
--- 針對性的錄入數據
mysql> insert into stu(sname,sfz)
-> values
-> ('w5','1233232');
mysql> select * from stu;
+----+-------+------+---------+---------+---------------------+
| id | sname | sage | sgender | sfz | intime |
+----+-------+------+---------+---------+---------------------+
| 1 | zs | 18 | m | 123456 | 2021-02-28 15:27:03 |
| 2 | ls | 18 | m | 1234567 | 2021-02-28 15:30:45 |
| 3 | w5 | 0 | n | 1233232 | 2021-02-28 15:32:24 |
+----+-------+------+---------+---------+---------------------+
--- 同時錄入多行數據
mysql> insert into stu(sname,sfz)
-> values
-> ('ll','34314314'),
-> ('kk','3515315'),
-> ('jj','654364365');
mysql> select * from stu;
+----+-------+------+---------+-----------+---------------------+
| id | sname | sage | sgender | sfz | intime |
+----+-------+------+---------+-----------+---------------------+
| 1 | zs | 18 | m | 123456 | 2021-02-28 15:27:03 |
| 2 | ls | 18 | m | 1234567 | 2021-02-28 15:30:45 |
| 3 | w5 | 0 | n | 1233232 | 2021-02-28 15:32:24 |
| 4 | ll | 0 | n | 34314314 | 2021-02-28 15:34:37 |
| 5 | kk | 0 | n | 3515315 | 2021-02-28 15:34:37 |
| 6 | jj | 0 | n | 654364365 | 2021-02-28 15:34:37 |
+----+-------+------+---------+-----------+---------------------+
insert into 庫.表 select concat(user,"@",host) from mysql.user;
update
mysql> update stu set sname='zhaosi' where id=1;
mysql> select * from stu;
+----+--------+------+---------+-----------+---------------------+
| id | sname | sage | sgender | sfz | intime |
+----+--------+------+---------+-----------+---------------------+
| 1 | zhaosi | 18 | m | 123456 | 2021-02-28 15:27:03 |
| 2 | ls | 18 | m | 1234567 | 2021-02-28 15:30:45 |
| 3 | w5 | 0 | n | 1233232 | 2021-02-28 15:32:24 |
| 4 | ll | 0 | n | 34314314 | 2021-02-28 15:34:37 |
| 5 | kk | 0 | n | 3515315 | 2021-02-28 15:34:37 |
| 6 | jj | 0 | n | 654364365 | 2021-02-28 15:34:37 |
+----+--------+------+---------+-----------+---------------------+
注意:update語句必須要加where。
delete
mysql> delete from stu where id=6;
mysql> select * from stu;
+----+--------+------+---------+----------+---------------------+
| id | sname | sage | sgender | sfz | intime |
+----+--------+------+---------+----------+---------------------+
| 1 | zhaosi | 18 | m | 123456 | 2021-02-28 15:27:03 |
| 2 | ls | 18 | m | 1234567 | 2021-02-28 15:30:45 |
| 3 | w5 | 0 | n | 1233232 | 2021-02-28 15:32:24 |
| 4 | ll | 0 | n | 34314314 | 2021-02-28 15:34:37 |
| 5 | kk | 0 | n | 3515315 | 2021-02-28 15:34:37 |
+----+--------+------+---------+----------+---------------------+
擴展
1、偽刪除
用update來替代delete,最終保證業務中查不到(select)即可
刪除id為1
原操作:
mysql> delete from stu where id=1;
偽刪除:
1.添加狀態列
ALTER TABLE stu ADD state TINYINT NOT NULL DEFAULT 1 ;
SELECT * FROM stu;
2. UPDATE 替代 DELETE
UPDATE stu SET state=0 WHERE id=6;
3. 業務語句查詢
SELECT * FROM stu WHERE state=1;
2、delete from stu ,drop table stu,truncate table stu的區別
1.都可以刪除全表
2.區別
delete
邏輯上,逐行刪除。數據行多,操作慢
並沒有真正從磁盤刪除,只是在存儲層面打標記,磁盤空間不立即釋放。HWM高水位線()不會降低。(自增列繼續)
drop
將表結構(元數據)和數據行物理層次刪除
truncate
清空表段中的所有數據頁。物理層次刪除全表數據磁盤空間立即釋放,HWM高水位會降低。(自增列重新開始)
#delete,drop,truncate如果不小心刪除了,他們都可以恢復嗎?
可以
常規方法:
都可以通過 備份+日志,恢復數據。
靈活辦法
delete可以通過,翻轉日志(binlog)
三種刪除數據情況,也可以通過《延時從庫進行恢復》
4、DQL
數據查詢語言
select
作用:獲取表中的數據行
1、select 單獨使用(MySQL獨家)
1.配合內置函數使用
mysql> select now(); #查看當前時間
mysql> select database(); #查看當前所在庫
mysql> select concat("hello word!"); #命令拼接,顯示某字符串
+-----------------------+
| concat("hello word!") |
+-----------------------+
| hello word! |
+-----------------------+
mysql> select concat(user,"@",host) from mysql.user;
+-------------------------+
| concat(user,"@",host) |
+-------------------------+
| root@10.0.0.1 |
| mysql.session@localhost |
| mysql.sys@localhost |
| root@localhost |
+-------------------------+
mysql> select user(); #查看當前登錄用戶
2.計算
mysql> select 10*100; #進行計算
+--------+
| 10*100 |
+--------+
| 1000 |
+--------+
3.查詢數據庫的參數
mysql> select @@port; #查詢當前端口
mysql> select @@datadir; #查看數據存儲位置
show variables; ##查看所有參數
mysql> show variables like '%trx%'; #like 模糊查詢
2、select 標准用法(配合其他子句使用)
單表
前提:
select
1.from 表1,表2,。。。
2.where 過濾條件1,過濾條件2...
3.group by 條件列1 條件列2。。。分組字段
4.select_list 列名
5.having 過濾條件1 過濾條件2。。。
6.order by 條件列1 條件列2。。。排序字段
7.limit 分頁限制
使用方法
准備學習環境[root@Centos7 ~]# mysql -p < world.sql 導入world庫
[root@Centos7 ~]# mysql -p < world.sql #導入world庫
world庫常見單詞
world ===>世界
city ===>城市
country ===>國家
countrylanguage ===>國家語言
city:城市表
DESC city;
ID : 城市ID
NAME : 城市名
CountryCode: 國家代碼,比如中國CHN 美國USA
District : 省份
Population : 人口數
1)select配合from子句使用
select配合from子句使用
語法:
select 列 from 表;
例子:
#查詢表中所有列所有行,*謹用!
select * from city;
#查詢部分列值
select name,population from city;
2)select+from+where配合使用
select+from+where配合使用
where配合比較判斷符=,<,>,>=,<=,!=
例子:
#查詢屬於中國的所有城市信息
mysql> select * from world.city where countrycode='CHN';
#查詢人口小於1000的所有城市信息
mysql> select * from world.city where population < 1000;
3)select+from+where+like配合使用,模糊查詢,針對字符串
select+from+where+like配合使用,模糊查詢
#查詢city中,國家代號是CH開頭的城市信息
mysql> select * from world.city where countrycode like 'CH%';
mysql> select * from world.city where countrycode like 'CH_';
%:多個任意字符
_:一個任意字符
注:like語句在使用時,切記不要出現前面帶%的模糊查詢,原因:不走索引。
#只要前面有%的模糊查詢,就不會走索引
select * from world.city where countrycode like '%CH%';
4)select+from+where+邏輯連接符(and or)
select+from+where+邏輯連接符(and or)
#例子:查詢中國城市人口超過500W的城市
mysql> select * from world.city
-> where countrycode='CHN' and population>5000000;
#查詢中國或美國的城市信息
mysql> select * from world.city where countrycode='CHN' or countrycode='USA';
#查詢中國和美國的信息,並且人口數量超過500W的城市;
mysql> select * from world.city where countrycode in ('CHN','USA') and population>5000000;
5)where配合between and,取一個范圍
where配合between and
#作用:查詢數值的一個范圍
#查詢人口在100W和兩百萬之前的城市信息
mysql> select * from world.city where population between 1000000 and 2000000;
mysql> select * from world.city where population>=1000000 and population<=2000000;
3、select+from+where+group by聚合函數
#作用:對一張表,按照不同數據特點,需要分組計算統計是,會使用group by+聚合函數
group by 配合聚合函數(max(),min(),avg(),count(),sum(),group_concat())使用
聚合函數:
max() #最大值
min() #最小值
avg() #平均值
count() #統計個數
sum() #求和
group_concat() #列轉行
#說明:碰到group_by必然會有聚合函數
運行過程:
提取數據--》排序--》去重--》統計
# 統計city中,每個國家的城市個數
select countrycode,count(id) from world.city group by countrycode;
# 統計中國每個省的城市個數
mysql> select district,count(id) from world.city where countrycode='CHN' group by district;
#統計每個國家的總人口
mysql> select countrycode,sum(population) from world.city group by countrycode;
#統計中國,每個省的總人口
mysql> select district,sum(population) from world.city where countrycode='CHN' group by district;
#統計中國,每個省總人口,城市個數,城市名列表
mysql> select district,sum(population),count(id),group_concat(name) from world.city where countrycode='CHN' group by district;
4、select+group by+having(后過濾)
#作用:與where作用相似,都是過濾作用,但having是后過濾 where|group by|having
#統計中國,每個省的總人口,只打印總人口數大於500W
mysql> select district,sum(population) from world.city where countrycode='CHN' group by district having sum(population)>5000000;
5、order by 排序
#作用:從小到大排序 默認由小到大添加desc后變成又大到小
#統計中國,每個省的總人口,只打印總人口數大於500W,並且按照總人口從大到小排序輸出
select district,sum(population) from world.city where countrycode='CHN' group by district having sum(population)>5000000 order by sum(population) desc;
默認升序:asc
降序:desc
6、limit 分頁
#作用:分頁輸出
#統計中國,每個省的總人口,只打印總人口數大於500W,並且按照總人口從大到小排序輸出,只看前五名
mysql> select district,sum(population) from world.city where countrycode='CHN' group by district having sum(population)>5000000 order by sum(population) desc limit 5;
#統計中國,每個省的總人口,只打印總人口數大於500W,並且按照總人口從大到小排序輸出,看6到10名
mysql> select district,sum(population) from world.city where countrycode='CHN' group by district having sum(population)>5000000 order by sum(population) desc limit 5,5;
mysql> select district,sum(population) from world.city where countrycode='CHN' group by district having sum(population)>5000000 order by sum(population) desc limit 5 offset 5;
##統計中國,每個省的總人口,只打印總人口數大於500W,並且按照總人口從大到小排序輸出,看3到5名
mysql> select district,sum(population) from world.city where countrycode='CHN' group by district having sum(population)>5000000 order by sum(population) desc limit 2,3;
mysql> select district,sum(population) from world.city where countrycode='CHN' group by district having sum(population)>5000000 order by sum(population) desc limit 3 offset 2;
7、distinct:去重復
#去重復
mysql> select countrycode from world.city;
mysql> select distinct(countrycode) from world.city;
8、聯合查詢 - union all
#查詢中國或美國的城市信息
mysql> select * from world.city where countrycode in ('CHN','USA');
mysql> select * from world.city where countrycode='CHN' union all select * from world.city where countrycode='USA';
#先查中國的再查美國的。
說明:一般情況下,我們會將 IN 或者 OR 語句 改寫成 UNION ALL,來提高性能
UNION 聚合兩個結果集,會自動去重復
UNION ALL 聚合兩個結果集,不去重復
9.join多表連接查詢
1)案例准備
按需求創建一下表結構
use school
student :學生表
sno: 學號
sname:學生姓名
sage: 學生年齡
ssex: 學生性別
teacher :教師表
tno: 教師編號
tname:教師名字
course :課程表
cno: 課程編號
cname:課程名字
tno: 教師編號
score :成績表
sno: 學號
cno: 課程編號
score:成績
-- 項目構建
drop database school;
CREATE DATABASE school CHARSET utf8mb4;
USE school
CREATE TABLE student(
sno INT NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '學號',
sname VARCHAR(20) NOT NULL COMMENT '姓名',
sage TINYINT UNSIGNED NOT NULL COMMENT '年齡',
ssex ENUM('f','m') NOT NULL DEFAULT 'm' COMMENT '性別'
)ENGINE=INNODB CHARSET=utf8;
CREATE TABLE course(
cno INT NOT NULL PRIMARY KEY COMMENT '課程編號',
cname VARCHAR(20) NOT NULL COMMENT '課程名字',
tno INT NOT NULL COMMENT '教師編號'
)ENGINE=INNODB CHARSET utf8;
alter TABLE sc (
sno INT NOT NULL COMMENT '學號',
cno INT NOT NULL COMMENT '課程編號',
score INT NOT NULL DEFAULT 0 COMMENT '成績'
)ENGINE=INNODB CHARSET=utf8;
CREATE TABLE teacher(
tno INT NOT NULL PRIMARY KEY COMMENT '教師編號',
tname VARCHAR(20) NOT NULL COMMENT '教師名字'
)ENGINE=INNODB CHARSET utf8;
INSERT INTO student(sno,sname,sage,ssex)
VALUES (1,'zhang3',18,'m');
INSERT INTO student(sno,sname,sage,ssex)
VALUES
(2,'zhang4',18,'m'),
(3,'li4',18,'m'),
(4,'wang5',19,'f');
INSERT INTO student
VALUES
(5,'zh4',18,'m'),
(6,'zhao4',18,'m'),
(7,'ma6',19,'f');
INSERT INTO student(sname,sage,ssex)
VALUES
('oldboy',20,'m'),
('oldgirl',20,'f'),
('oldp',25,'m');
INSERT INTO teacher(tno,tname) VALUES
(101,'oldboy'),
(102,'hesw'),
(103,'oldguo');
DESC course;
INSERT INTO course(cno,cname,tno)
VALUES
(1001,'linux',101),
(1002,'python',102),
(1003,'mysql',103);
DESC sc;
INSERT INTO sc(sno,cno,score)
VALUES
(1,1001,80),
(1,1002,59),
(2,1002,90),
(2,1003,100),
(3,1001,99),
(3,1003,40),
(4,1001,79),
(4,1002,61),
(4,1003,99),
(5,1003,40),
(6,1001,89),
(6,1003,77),
(7,1001,67),
(7,1003,82),
(8,1001,70),
(9,1003,80),
(10,1003,96);
SELECT * FROM student;
SELECT * FROM teacher;
SELECT * FROM course;
SELECT * FROM sc;
2)介紹
將多張表合成一張大表
查詢張三的家庭住址
SELECT A.name,B.address FROM
A JOIN B
ON A.id=B.id
WHERE A.name='zhangsan'
3)作用
1、為什么要使用多表連接查詢?
我們的查詢需求,需要的數據,來自於多張表,單張表無法滿足。
2、簡單理解:
多表連接實際上是將多張表中,有關聯的部分數據,合並成一張新表,在新表中去做 where、group、having、order by、limit
4)多表連接查詢的類型
1.笛卡爾乘積(不常見)
mysql> select * from teacher,course;
+-----+--------+------+--------+-----+
| tno | tname | cno | cname | tno |
+-----+--------+------+--------+-----+
| 101 | oldboy | 1001 | linux | 101 |
| 102 | hesw | 1001 | linux | 101 |
| 103 | oldguo | 1001 | linux | 101 |
| 101 | oldboy | 1002 | python | 102 |
| 102 | hesw | 1002 | python | 102 |
| 103 | oldguo | 1002 | python | 102 |
| 101 | oldboy | 1003 | mysql | 103 |
| 102 | hesw | 1003 | mysql | 103 |
| 103 | oldguo | 1003 | mysql | 103 |
+-----+--------+------+--------+-----+
9 rows in set (0.00 sec)
mysql> select * from teacher join course;
+-----+--------+------+--------+-----+
| tno | tname | cno | cname | tno |
+-----+--------+------+--------+-----+
| 101 | oldboy | 1001 | linux | 101 |
| 102 | hesw | 1001 | linux | 101 |
| 103 | oldguo | 1001 | linux | 101 |
| 101 | oldboy | 1002 | python | 102 |
| 102 | hesw | 1002 | python | 102 |
| 103 | oldguo | 1002 | python | 102 |
| 101 | oldboy | 1003 | mysql | 103 |
| 102 | hesw | 1003 | mysql | 103 |
| 103 | oldguo | 1003 | mysql | 103 |
+-----+--------+------+--------+-----+
9 rows in set (0.00 sec)
2.內連接(應用最廣泛)
select 列名。。。
from A join B
on A.xx=B.yy
mysql> select * from teacher join course on teacher.tno=course.tno;
+-----+--------+------+--------+-----+
| tno | tname | cno | cname | tno |
+-----+--------+------+--------+-----+
| 101 | oldboy | 1001 | linux | 101 |
| 102 | hesw | 1002 | python | 102 |
| 103 | oldguo | 1003 | mysql | 103 |
+-----+--------+------+--------+-----+
3.外連接
#作用:強制驅動表
驅動表:在多表連接中,承當for循環中外層循環的角色,此時,MySQL會拿着驅動表的每個滿足條件的關聯列的值,去一次找到for循環內循環中的關聯值一一進行判斷和匹配。(next loop)。
建議:將結果集小的表設置為驅動表更加合適,可以降低next loop的次數。對於內連接來講,我們是沒法控制驅動表是誰,完全由優化器決定。如果需要人為干預,需要將內連接寫成外連接的方式。
1、left join #左邊的所有的數據列都要取到,右表滿足條件的數據,強制左表為驅動表
mysql> select city.name,country.name,city.population from city left join country on city.countrycode = country.code and city.population<100 order by city.population desc;
2、right join #右邊的所有的數據列都要取到,左表滿足條件的數據,強制右表為驅動表
mysql> select city.name,country.name,city.population from city right join country on city.countrycode = country.code and city.population<100;
5)全外連接
mysql> select city.name,country.name,city.population from city left join country on city.countrycode = country.code and city.population<100 order by city.population desc
union
mysql> select city.name,country.name,city.population from city right join country on city.countrycode = country.code and city.population<100;
6)多表連接查詢例子(內連接)
例子一:查詢wuhan這個城市,國家名、城市名、城市人口數、國土面積。
1、找關聯表:
city:
城市名(city.name)
城市人口(city.population)
country:
國家名(country.name)
國土面積(country.surfacearea)
from city join country
2、找關聯條件
mysql> desc city;
mysql> desc country;
#發現city.countrycode和country.code有關聯
from city join country on city.countrycode=country.code
3、羅列其他查詢條件
mysql>
select city.name,
city.population,
country.name,
country.surfacearea
from city
join country
on city.countrycode=country.code
where city.name='wuhan';
例子二:統計學員zhang3,學習了幾門課
1、找關聯表
student.sname
count(sc.cno)
from student join sc
2、找關聯條件
from student join sc
on student.sno=sc.sno
3、羅列其他條件
mysql> select student.sno as 學號,
student.sname as 學生姓名,
count(sc.cno) as 學習課數
from sc
join student
on sc.sno=student.sno
where student.sname='zhang3'
group by student.sno;
+--------+--------------+--------------+
| 學號 | 學生姓名 | 學習課數 |
+--------+--------------+--------------+
| 1 | zhang3 | 2 |
+--------+--------------+--------------+
例子三:查詢zhang3,學習的課程名稱有哪些
1、找關聯表
student.sname
sc.sno,sc.cno
course.cname
2、找關聯條件
student.sname
sc.sno,sc.cno
course.cname
from student
join sc
on student.sno = sc.sno
join course
on sc.cno = course.cno
3、羅列條件
mysql> select student.sno as 學號,
student.sname as 學生姓名,
group_concat(course.cname) as 課程名稱
from student
join sc
on student.sno=sc.sno
join course
on sc.cno=course.cno
where student.sname='zhang3'
group by student.sno;
+--------+--------------+--------------+
| 學號 | 學生姓名 | 課程名稱 |
+--------+--------------+--------------+
| 1 | zhang3 | python,linux |
+--------+--------------+--------------+
例子四:查詢oldguo老師教的學生名
1、找關聯條件、關聯表
select teacher.tname,student.sname
on teacher.tno = course.tno
on course.cno = sc.cno
on sc.sno = student.sno
2、羅列條件
select teacher.tname,
group_concat(student.sname)
from teacher
join course
on teacher.tno = course.tno
join sc
on course.cno = sc.cno
join student
on sc.sno = student.sno
where teacher.tname='oldguo';
例子五:查詢oldguo所教課程的平均分數
select teacher.tname,avg(sc.score)
from teacher
join course
on teacher.tno = course.tno
join sc
on course.cno = sc.cno
where teacher.tname='oldguo';
例子六:每位老師所教課程的平均分,並按平均分排序
mysql> select teacher.tname,
avg(sc.score)
from teacher
join course
on teacher.tno = course.tno
join sc
on course.cno = sc.cno
group by teacher.tname
order by avg(sc.score)
desc;
+--------+---------------+
| tname | avg(sc.score) |
+--------+---------------+
| oldboy | 80.6667 |
| oldguo | 76.7500 |
| hesw | 70.0000 |
+--------+---------------+
例子七:查詢oldguo所教的不及格的學生姓名
mysql> select teacher.tname,
student.sname,
sc.score
from teacher
join course
on teacher.tno = course.tno
join sc
on course.cno = sc.cno
join student
on sc.sno = student.sno
where teacher.tname='oldguo'
and sc.score < 60;
+--------+-------+-------+
| tname | sname | score |
+--------+-------+-------+
| oldguo | li4 | 40 |
| oldguo | zh4 | 40 |
+--------+-------+-------+
例子八:查詢所有老師所教學生不及格的信息
mysql> select teacher.tname, student.sname, sc.score from teacher join course on teacher.tno = course.tno join sc on course.cno = sc.cno join student on sc.sno = student.sno where sc.score < 60;
+--------+--------+-------+
| tname | sname | score |
+--------+--------+-------+
| hesw | zhang3 | 59 |
| oldguo | li4 | 40 |
| oldguo | zh4 | 40 |
+--------+--------+-------+
例子九:查詢平均成績大於60分的同學的學號和平均成績
select student.sno,
student.sname,
avg(sc.score)
from student
join sc
on student.sno=sc.sno
group by student.sno
having avg(sc.score)>60;
例子十:查詢所有同學的學號、姓名、選課數、總成績、平均成績
select student.sno,
student.sname,
count(*),
sum(sc.score),
avg(sc.score)
from student
join sc
on student.sno = sc.sno
group by student.sno;
例子十一:查詢各科成績的最高分和最低分:以如下形式顯示:課程ID,最高分,最低分***
select sc.cno as 課程id,
max(sc.score) as 最高分,
min(sc.score) as 最低分
from sc
group by sc.cno;
例子十二:統計各位老師,所教課程的及格率(及格人數/總人數)***
##case語法
case when 判斷 then 結果 end
#
select teacher.tname as 教師姓名,
concat(count(case when sc.score>60 then 1 end)/count(*)*100,"%") as 及格率
from teacher
join course
on teacher.tno = course.tno
join sc
on course.cno = sc.cno
group by teacher.tno;
例子十三:查詢出只選修了一門課程的全部學生的學號和姓名
select student.sno ,student.sname,count(*)
from student
join sc
on student.sno = sc.sno
group by student.sno
having count(*) = 1;
例子十五:查詢選修課程門數超過1門的學生信息
select student.sno ,student.sname,count(*)
from student
join sc
on student.sno = sc.sno
group by student.sno
having count(*) > 1;
例子十六:統計每門課程優秀(85分以上),良好(70-85),一般(60-70),不及格(小於60)的學生列表***
select course.cname,
group_concat(
case when sc.score>=85
then student.sname
end) as 優秀,
group_concat(
case when sc.score>=70
and sc.score<85
then student.sname
end) as 良好,
group_concat(
case when sc.score>=60
and sc.score<70
then student.sname
end) as 一般,
group_concat(
case when sc.score<60
then student.sname
end) as 不及格
from student
join sc
on student.sno=sc.sno
join course
on sc.cno=course.cno
group by course.cno;
例子十七:查詢平均成績大於85的所有學生的學號、姓名和平均成績
select student.sno,
student.sname,
avg(sc.score)
from student
join sc
on student.sno=sc.sno
group by student.sno
having avg(sc.score)>85;
別名
#別名是一次性的名字,僅限當前select使用。但可以在全局調用定義的別名
列別名,表別名
SELECT
a.Name AS an ,
b.name AS bn ,
b.SurfaceArea AS bs,
a.Population AS bp
FROM city AS a JOIN country AS b
ON a.CountryCode=b.Code
WHERE a.name ='shenyang';
mysql> select city.name,city.population,country.name,country.surfacearea from city join country on city.countrycode=country.code where city.name='wuhan';
+-------+------------+-------+-------------+
| name | population | name | surfacearea |
+-------+------------+-------+-------------+
| Wuhan | 4344600 | China | 9572900.00 |
+-------+------------+-------+-------------+
mysql> select city.name as 城市名,city.population as 城市人口,country.name as 國家名,country.surfacearea as 國土面積 from city join country on city.countrycode=country.code where city.name='wuhan';
+-----------+--------------+-----------+--------------+
| 城市名 | 城市人口 | 國家名 | 國土面積 |
+-----------+--------------+-----------+--------------+
| Wuhan | 4344600 | China | 9572900.00 |
+-----------+--------------+-----------+--------------+
show語句
show databases; #查看所有數據庫
show tables; #查看當前庫的所有表
SHOW tables from #查看某個指定庫下的表
show create database world #查看建庫語句
show create table world.city #查看建表語句
show grants for root@'localhost' #查看用戶的權限信息
show charset; #查看字符集
show collation #查看校對規則
show processlist; #查看數據庫連接情況
show full processlist; #查看數據庫連接情況,且顯示info的詳細信息
show privileges #查看支持的權限信息
show index from #表的索引情況
show status #數據庫狀態查看
SHOW STATUS LIKE '%lock%'; #模糊查詢數據庫某些狀態
SHOW variables #查看所有配置信息
SHOW variables LIKE '%lock%'; #模糊查看部分配置信息
show engines #查看支持的所有的存儲引擎
show engine innodb status\G #查看InnoDB引擎相關的狀態信息
show binary logs #列舉所有的二進制日志
show master status #查看數據庫的日志位置信息
show binlog evnets #查看二進制日志事件
show master status; #查詢二進制日志的位置點信息
show slave status\G #查看從庫狀態
SHOW RELAYLOG EVENTS in #查看從庫relaylog事件信息,查看中繼日志事件
desc (show colums from city) #查看表的列定義信息
http://dev.mysql.com/doc/refman/5.7/en/show.html