柚子快報邀請碼778899分享:數(shù)據(jù)庫 MySQL詳解
柚子快報邀請碼778899分享:數(shù)據(jù)庫 MySQL詳解
一、MySQL介紹
1.1 引言
之前在學習JavaSE基礎(chǔ)時,存儲數(shù)據(jù)的方式有哪些?
Java程序存儲數(shù)據(jù)(變量,對象,數(shù)組,集合),數(shù)據(jù)都會被存儲在Java內(nèi)存中,屬于瞬時狀態(tài)存儲?;贗O的方式,將Java內(nèi)存中的數(shù)據(jù),持久化到本地的一個文件中,保存到硬盤上,屬于持久狀態(tài)存儲。
上述的存儲方式存在什么問題呢?
基于內(nèi)存存儲數(shù)據(jù),明顯不安全,JVM一停,數(shù)據(jù)沒了,非常不安全。如果采用IO的形式,存儲到本地文件
沒有數(shù)據(jù)類型的區(qū)分,會導致操作持久化的數(shù)據(jù)很麻煩。存儲的數(shù)據(jù)量級比較小,如果將1個G的數(shù)據(jù)存到一個文件里,很難維護。沒有訪問的安全限制。沒有做備份,和誤操恢復的能力。想查詢某一個數(shù)據(jù),但是很難找。
1.2 數(shù)據(jù)庫
數(shù)據(jù)庫是按照數(shù)據(jù)結(jié)構(gòu)來組織,存儲和管理數(shù)據(jù)的倉庫。是一個長期存儲在計算機內(nèi)的,有組織的,有共享的統(tǒng)一管理的數(shù)據(jù)集合。
數(shù)據(jù)庫的分類其他非常多,咱們現(xiàn)在只需要關(guān)注兩種即可:
關(guān)系型數(shù)據(jù)庫:Oracle、MySQL、SQL Server、PostgreSQL、DB2,這些都是以表格Table的形式存儲,多表格之間建立關(guān)聯(lián)關(guān)系,通過分類,合并,連接,選取以及一些運算進行訪問。非關(guān)系型數(shù)據(jù)庫:Redis、Elasticsearch、MongoDB、HBase等等都屬于非關(guān)系型數(shù)據(jù)庫,他們的存儲方式各有各的道。
1.3 MySQL介紹
MySQL屬于 關(guān)系型數(shù)據(jù)庫 ,由瑞典的MySQL AB公司開發(fā),屬于Oracle旗下的產(chǎn)品。MySQL依然是最主流的關(guān)系型數(shù)據(jù)庫之一,在WEB應(yīng)用方面,MySQL是最好的關(guān)系型數(shù)據(jù)庫之一。
MySQL官網(wǎng):https://www.mysql.com/
現(xiàn)在關(guān)系型數(shù)據(jù)庫的種類還是比較多的,每種數(shù)據(jù)庫的操作方式會有一些不同,但是大方向上基本都是一樣的,關(guān)系型數(shù)據(jù)庫,后期都基于SQL語句做基本交互,每個數(shù)據(jù)庫都是基于SQL99規(guī)范。但是一些細節(jié)內(nèi)容可能會有一些不同,但是大方向基本沒有特別大的區(qū)別。
二、MySQL下載&安裝
MySQL現(xiàn)在的主流版本就是5.7和8.0,如果你電腦上已經(jīng)有這兩個版本的任意版本,不要卸載再安裝,成本蠻高的。
2.1 安裝MySQL 5.7(別跳過)
首先去官網(wǎng)下載MySQL 5.7的安裝包。
下載好一個Windows環(huán)境下的安裝包,不需要做太多的額外操作,基本就是傻瓜式安裝,不停的下一步下一步下一步下一步…………
到這,MySQL5.7就安裝好了。同時可以測試一下鏈接效果。
也可以配置一下環(huán)境變量,找一下MySQL的默認安裝地址
我沒指定安裝地址,默認就是這:C:\Program Files\MySQL\MySQL Server 5.7\bin
將這個路徑配置到環(huán)境變量的Path里。
配置好之后, 重新打開一個cmd窗口?。。。。?鏈接
2.2 安裝MySQL 8.0
看8.0之前,看一下5.7的安裝,流程基本都是一致的。
跟5.7一樣,去逛網(wǎng)下載MySQL的安裝包,這次下載的是8.0的版本
下載好之后,直接打開即可。
這次安裝流程一致,只是安裝的服務(wù)是8.0的,沒貼圖的,就是和MySQL5.7一樣的操作
安裝成功后,測試一下鏈接。
環(huán)境變量和MySQL5.7的方式是一樣的。
重新打開一個cmd窗口!?。。?!鏈接
三、SQL語言
3.1 概念
SQL(Structured Query Language)結(jié)構(gòu)化查詢語言。SQL用于對存儲數(shù)據(jù),更新,查詢和管理關(guān)系型數(shù)據(jù)庫的程序設(shè)計語言。
通常執(zhí)行對數(shù)據(jù)庫的增刪改查,簡稱C(Create)R(Read)U(Update)D(Delete)
在MySQL中有一點:
對于數(shù)據(jù)庫的操作,需要進入的MySQL環(huán)境下進行指令輸入,屬于完一個語句,需要使用 ; 進行結(jié)尾。
3.2 基本操作
在做基本操作之前,先要對MySQL的整體結(jié)構(gòu)有一個了解。
一個MySQL服務(wù)下會有很多個庫,其中MySQL中會自帶4個庫,下面綠色的標識。
這四個不要動。要玩的話,需要自己主動的去創(chuàng)建數(shù)據(jù)庫。
開始操作,首先用doc窗口,或者用MySQL提供的命令窗口去進入到MySQL環(huán)境。
查看MySQL中所有的數(shù)據(jù)庫
mysql> show databases; # 顯示當前MySQL中包含的所有數(shù)據(jù)庫
數(shù)據(jù)庫名稱描述information_schema信息數(shù)據(jù)庫,保存著關(guān)乎所有數(shù)據(jù)庫的信息(元數(shù)據(jù))。mysql核心數(shù)據(jù)庫,主要負責存儲數(shù)據(jù)庫的用戶,權(quán)限設(shè)置,關(guān)鍵字等等。performance_schema性能優(yōu)化的數(shù)據(jù)庫,性能優(yōu)化的引擎等等都在里面。sys系統(tǒng)數(shù)據(jù)庫存儲元數(shù)據(jù)信息的庫,可以了解系統(tǒng)瓶頸的問題。
創(chuàng)建自定義的數(shù)據(jù)庫
mysql> create database 數(shù)據(jù)庫名稱;
mysql> create database 數(shù)據(jù)庫名稱 character set utf8mb4;
mysql> create database if not exists 數(shù)據(jù)庫名稱;
查看數(shù)據(jù)庫創(chuàng)建信息
mysql> show create database 數(shù)據(jù)庫名稱; # 查看數(shù)據(jù)庫創(chuàng)建時的基本信息
修改數(shù)據(jù)庫(了解)
mysql> alter database 數(shù)據(jù)庫名稱 character set gbk; # 修改數(shù)據(jù)庫的字符集
刪除數(shù)據(jù)庫
mysql> drop database 數(shù)據(jù)庫名稱;
使用數(shù)據(jù)庫
mysql> use 數(shù)據(jù)庫名稱;
查看當前所使用的數(shù)據(jù)庫
mysql> select database(); # 查看當前使用的是哪個數(shù)據(jù)庫
四、客戶端工具
這里就帶領(lǐng)大家安裝一個Navicat工具。
類似其他的客戶端工具就不帶領(lǐng)大家去玩了,咱們就接觸Navicat就足夠了。
安裝OK之后,直接基于Navicat對MySQL做一些基本的操作
指定上各種連接信息后,會發(fā)現(xiàn)Navicat無法正常連接,原因是因為MySQL升級到8.0版本之后,采用的加密方式是caching_sha2_password,這種加密導致8.0的版本用遠程工具無法正常的鏈接,需要將現(xiàn)在用的root用戶的密碼加密方式,修改為mysql_native_password的方式。
用黑窗口,連接上MySQL服務(wù),在內(nèi)部執(zhí)行下面的指令
mysql> alter user 'root'@'localhost' identified with mysql_native_password by '密碼';
鏈接數(shù)據(jù)庫成功后,會看到這個界面
五、DQL操作(重要)
5.1 數(shù)據(jù)庫表的基本結(jié)構(gòu)
關(guān)系結(jié)構(gòu)數(shù)據(jù)庫的是以表格(Table)進行數(shù)據(jù)的存儲,表格由 行 和 列 組成。
這里提供了一套test庫的表和測試數(shù)據(jù),后面操作都基于這幾張表來玩。
構(gòu)建好test庫,將課程資料中提供的test.sql文件,直接拖拽到表的位置
導入之后,關(guān)閉,需要在表的位置按F5,刷新一波。
5.2 基本查詢
語法:SELECT 列名 FROM 表名
關(guān)鍵字描述SELECT指定要查詢的列FROM指定要查詢的表
5.2.1 查詢部分列
-- 查詢員工表中的員工id,名稱,郵件。
-- MySQL中可以忽略列名的大小寫,表名也可以忽略。
SELECT
employee_id,first_name,last_name,email
FROM
t_employees;
5.2.2 查詢所有列
在公司中開發(fā)的過程中,哪怕你有200個列,需要查詢200個,你也必須寫200個列。 在自己玩的時候,為了提升學習的速度,可以通過 * 來代表所有的列。
*這個關(guān)鍵字,可以放在SELECT的后面,代表所有的列。
-- 查詢?nèi)康牧?/p>
SELECT
*
FROM
t_employees;
5.2.3 對列中的數(shù)據(jù)進行運算
查詢員工表中,員工的名稱,以及所有員工的年薪是多少(12個月的薪資)
-- 查詢員工表中,員工的名稱,以及所有員工的年薪是多少(12個月的薪資)
SELECT
first_name,last_name,salary * 12
FROM
t_employees;
算術(shù)運算符描述+兩列做加法運算-兩列做減法運算*兩列做乘法運算/兩列做除法運算
Ps:%符號,不是取模,在MySQL中,%屬于一個通配符。
5.2.4 列的別名
查詢員工表中,員工的名稱,以及所有員工的年薪是多少(12個月的薪資),同時給返回的虛擬表的列設(shè)置中文名稱
可以在查詢的列后面,追加上as關(guān)鍵字,然后指定返回的列的別名
也可以簡寫,不寫as,直接在查詢的列后面追加列的別名
SELECT
first_name as "名", last_name as "姓", salary * 12 年薪
FROM
t_employees;
5.2.5 查詢結(jié)果去重
通過員工表,查詢部門ID。
-- 通過員工表,查詢部門ID
SELECT
department_id
FROM
t_employees
通過員工表,查詢部門ID,不查看重復數(shù)據(jù),去重。
DISTINCT放在所有列名的最前面,會幫你把數(shù)據(jù)重復的行,去掉。
-- 通過員工表,查詢部門ID,不查看重復數(shù)據(jù),去重.
SELECT
DISTINCT department_id
FROM
t_employees
5.3 排序查詢
在執(zhí)行SELECT查詢后,查詢到的結(jié)果一般是跟表中的結(jié)果順序一致的。
如果需要基于一些列做排序,可以使用MySQL提供的order by 操作
語法: SELECT 列名 FROM 表名 ORDER BY 排序列 [排序規(guī)則] , 排序列 [排序規(guī)則] …………
排序規(guī)則描述ASC(默認規(guī)則)對前面排序列做升序排序DESC對前面排序列做降序排序
查詢員工的編號,姓,薪資。 按照薪資的高低做降序排序
# 查詢員工的編號,姓,薪資。 按照薪資的高低做降序排序
SELECT
employee_id,last_name, salary
FROM
t_employees
ORDER BY
salary DESC
查詢員工的姓,工資,入職時間。 優(yōu)先按照工資做降序,再根據(jù)入職時間做升序
-- 查詢員工的姓,工資,入職時間。 優(yōu)先按照工資做降序,再根據(jù)入職時間做升序
-- 運行選中的SQL的快捷鍵 ,Ctrl + Shift + R
SELECT
last_name 姓, salary 工資, hire_date 入職時間
FROM
t_employees
ORDER BY
salary DESC,
hire_date
5.4 條件查詢
語法:select 列明 from 表名 where 條件
關(guān)鍵字描述where在查詢結(jié)果中,篩選符合條件的查詢結(jié)果,條件為布爾表達式
5.4.1 等值判斷(=)
注意:與Java不中,Java中是==,而在MySQL中是=
查詢薪資是11000的員工信息。(查詢員工的編號,名稱,薪資)
select
employee_id,first_name ,salary
from
t_employees
where
salary = 11000;
5.4.2 不等值判斷(<、>、<=、>=、!=、<>)
其中,前四個沒啥說的,常規(guī)的大于,小于之類的判斷。
其中 != 和 <> 都代表不等于的意思。
查詢薪資是大于11000員工信息。(查詢員工的編號,名稱,薪資)
select
employee_id,first_name ,salary
from
t_employees
WHERE
salary > 11000;
5.4.3 邏輯判斷(and,or,not)
類似Java中的 && ,|| ,!
其中 and 左右的條件都需要滿足才可以。
其中 or 左右的條件,滿足其一就可以查詢到。
其中 not 會將條件取反
查詢薪資是11000大洋,并且提成是0.3的員工信息(查詢員工的編號,名稱,薪資,提成)
select
employee_id,first_name ,salary ,commission_pct
from
t_employees
where
salary = 11000 and commission_pct = 0.3;
5.4.4 區(qū)間查詢(between 數(shù)值 and 數(shù)值)
這個between and其實就相當于 用大于等于和小于等于的組合。
包含邊界的。
需要指定好字段值的邊界。并且需要左側(cè)的數(shù)值小,右側(cè)的數(shù)值大。不然無法查詢到結(jié)果。
查詢員工的薪資在5000~10000之間的員工信息。(查詢員工的編號,名稱,薪資)
select
employee_id,first_name ,salary
from
t_employees
where
salary between 5000 and 10000;
5.4.5 NULL 值判斷(is null、is not null)
當對某個列判斷是否是NULL值時,不能使用 = 或者 != 之類的方式。
必須采用 字段 is null 、 字段 is not null 的方式
查詢沒有提成的員工信息(查詢員工的編號,名稱,薪資,提成)
select
employee_id,first_name ,salary,commission_pct
from
t_employees
where
commission_pct is not null;
5.4.6 字段多值判斷(in)
正常如果涉及到了某一個字段,可以為多個值的匹配條件時。
正??赡苄枰?字段 = xxx or 字段 = yyy or 字段 = zzz。 寫著成本太高。
可以采用in來實現(xiàn)。
字段 in (xxx,yyy,zzz)
查詢員工屬于60,70,80,90號部門的員工信息。(查詢員工的編號,名稱,薪資,部門編號)
select
employee_id,first_name ,salary,department_id
from
t_employees
where
department_id in (60,70,80,90);
5.4.7 模糊查詢(like)
模糊查詢一般是來匹配字符串的。
其中有兩個關(guān)鍵字。 % _
字段 like ‘s%’ :查詢出這個字段中以s開頭的數(shù)據(jù)。
字段 like ‘s_’ :查詢出s開頭,并且后面只有一個字符
%:代表任意長度的任意字符
_:代表單個任意字符
Ps:這兩個特殊字符只能配合like使用
查詢名字以L開頭的員工信息(查詢員工的編號,名稱,薪資)
select
employee_id,first_name ,salary
from
t_employees
where
first_name like 'L%'
查詢名字以L開頭,但是名字長度為4個字符的員工信息(查詢員工的編號,名稱,薪資)
select
employee_id,first_name ,salary
from
t_employees
where
first_name like 'L___'
5.4.8 分支結(jié)構(gòu)查詢(case when then else end)
語法:這里的分支結(jié)構(gòu)查詢一般是放在select后面的特殊操作。
case
when 條件1 then 結(jié)果1
when 條件2 then 結(jié)果2
when 條件3 then 結(jié)果3
………………
else 結(jié)果
end
可以認為是case開頭,end結(jié)尾,中間寫when then的內(nèi)容
就是類似Java中的switch
查詢員工信息,并根據(jù)薪資范圍,體現(xiàn)出員工的薪資等級
salary 0 ~ 4000 = E
salary 4000 ~ 6000 = D
salary 6000 ~ 8000 = C
salary 8000 ~ 10000 = B
salary 10000 ~ …… = A
select
employee_id,first_name ,salary ,
case
when salary >= 0 and salary < 4000 then 'E'
when salary >= 4000 and salary < 6000 then 'D'
when salary >= 6000 and salary < 8000 then 'C'
when salary >= 8000 and salary < 10000 then 'B'
else 'A'
end as salary_level
from
t_employees;
5.4.9 邏輯判斷(if、ifnull)
這里的if,和ifnull類似于Java中調(diào)用方法實現(xiàn)某個功能。
if(條件表達式,結(jié)果1,結(jié)果2):條件表達式為true,返回結(jié)果1,否則返回結(jié)果2
ifnull(值,結(jié)果):如果值為NULL,返回結(jié)果,如果值不為NULL,返回值本身。
查詢員工信息,如果薪資大于10000,返回小康生活,否則,返回勉強生存(查詢員工的編號,名稱,薪資)
select
employee_id,first_name ,salary,if(salary > 10000,'小康生活','勉強生存')
from
t_employees;
查詢員工號信息,如果有提成,返回提升的比例,如果沒有,返回吃底薪。(查詢員工的編號,名稱,薪資)
select
employee_id,first_name ,salary,ifnull(commission_pct,'吃底薪')
from
t_employees;
5.5 時間函數(shù)查詢
這里是針對MySQL中的時間類型提供的一些函數(shù)以及操作。
下面會玩一些關(guān)于時間函數(shù)的操作。
時間函數(shù)描述sysdate()返回當前系統(tǒng)時間,返回年-月-日 時:分:秒now()返回當前系統(tǒng)時間,返回年-月-日 時:分:秒curdate()返回當前系統(tǒng)的年月日curtime()返回當前系統(tǒng)的時分秒week(date)返回指定日期是今年的第幾周year(date)返回指定日期的年month(date)返回指定日期的月day(date)返回指定日期的日hour、minute、second(date)返回指定日期的時、分、秒
5.6 字符串函數(shù)查詢
針對字符串的一些函數(shù)。
函數(shù)描述concat(str1,str2,str…)將多個字符串拼接到一起……upper、lower(str)upper是將字符串切換為大寫、lower將字符串切換為小寫substring(str,num,len)將字符串從num位置開啟截取len個內(nèi)容,num從1開始insert(str,pos,len,newstr)將str中指定的pos位置開始len長度的內(nèi)容替換為newStrreplace(str,from_str,to_str)將str中所有的from_str,替換為to_strdate_format(date,format)將時間類型date,根據(jù)format的格式轉(zhuǎn)換為varcharstr_to_date(str,format)將字符串類varchar,根據(jù)format的格式轉(zhuǎn)換為date
format:%Y-%m-%d %H:%i:%s 表示 yyyy-MM-dd HH:mm:ss
5.7 聚合函數(shù)查詢
針對多行數(shù)據(jù)做的一個統(tǒng)計。
一般有五種需要咱們掌握
語法: select 聚合函數(shù)(列名) from 表名;
函數(shù)名描述sum(列名)統(tǒng)計當前列所有數(shù)據(jù)的總和max(列名)獲取到當前列中的最大值min(列名)獲取到當前列中的最小值avg(列名)獲取到當前列中所有數(shù)據(jù)的平均值count(列名)獲取當前數(shù)據(jù)的總條數(shù)
基于上述的聚合函數(shù),針對薪資做一個統(tǒng)計,分別統(tǒng)計薪資總和,薪資最大值,薪資最小值,薪資的平均值,當前員工的個數(shù)。
一般都是針對數(shù)值類型的字段做具體的統(tǒng)計,幾乎不會對字符串做什么統(tǒng)計操作,count除外。
select
sum(salary) 薪資總和, max(salary) 薪資最大值, min(salary) 薪資最小值,avg(salary) 薪資平均值, count(*) 員工的個數(shù)
from
t_employees;
5.8 分組查詢
語法:select 列名 from 表名 where 條件 group by 列名
查詢各部門的人數(shù)(查詢部門編號,部門對應(yīng)的人數(shù))
select
department_id 部門編號, count(*) 部門人數(shù)
from
t_employees
group by department_id;
查詢各個部門的平均工資(查詢部門編號,部門的平均工資)
select
department_id 部門編號, avg(salary) 平均工資
from
t_employees
group by department_id;
查詢各個部門、各個崗位的人數(shù)(部門編號,崗位信息,人數(shù))
1、根據(jù)department_id分組。
2、根據(jù)job_id分組
3、做count統(tǒng)計查詢
select
department_id 部門編號, job_id 崗位信息, count(*) 人數(shù)
from
t_employees
group by department_id,job_id;
# 查詢各個部門、各個崗位,薪資大于5000的人數(shù)(部門編號,崗位信息,人數(shù))
select
department_id 部門編號, job_id 崗位信息, count(*) 人數(shù)
from
t_employees
where
salary > 5000
group by department_id,job_id;
5.9 分組過濾查詢
如果需要在做過分組之后,再次對接過做二次篩選,需要使用having的方式編寫條件
語法: select 列名 from 表名 where 條件 group by 列名 having 條件 order by 列名
查詢各個部門、各個崗位的人數(shù)(部門編號,崗位信息,人數(shù)),只查看人數(shù)大于10個的
select
department_id 部門編號, job_id 崗位信息, count(*) 人數(shù)
from
t_employees
group by department_id,job_id
having 人數(shù) > 10;
查詢各個部門中,平均薪資大于10000的部門信息(部門編號,平均薪資)
select
department_id 部門編號,avg(salary) avg_salary
from
t_employees
group by department_id
having avg_salary > 10000;
# 查詢各個部門中,所有員工平均薪資大于10000的部門信息(部門編號,平均薪資),在根據(jù)平均薪資做排序
select
department_id 部門編號,avg(salary) avg_salary
from
t_employees
group by department_id
having avg_salary > 10000
order by avg_salary asc;
5.10 限定查詢
比如查詢時,查詢到了上千條的數(shù)據(jù),但是暫時只需要前5條,可以基于limit只獲取前5條數(shù)據(jù)返回。
采用limit幫助咱們實現(xiàn)。 limit是MySQL特有的一個關(guān)鍵字。
語法:select 列名 from 表名 where 條件 group by 列名 having 條件 order by 列名 limit 起始行,行數(shù)
起始行(offset):你返回的數(shù)據(jù),從第幾行開始, 從第0行開始。
行數(shù)(size):一共返回幾行數(shù)據(jù)
limit 0,5:從第一行數(shù)據(jù)開始,往下一共返回5條。
limit的第一個offset可以省略不寫,不寫代表寫的是0。
查詢表中薪資最高的前5名員工的所有信息。
薪資最高的話,需要基于salary做降序排序?;趌imit,只返回前5條數(shù)據(jù)。
select
*
from
t_employees
order by salary desc
limit 0,5
查詢表中薪資最高的6~10名員工的所有信息。
select
*
from
t_employees
order by salary desc
limit 5,5
limit很多時候可以同于分頁操作,比如需要分頁時
可以采用limit,在數(shù)據(jù)庫中查詢到不同頁數(shù)的數(shù)據(jù),給頁面返回,讓頁面展示數(shù)據(jù)即可。
5.11 子查詢
查詢語句返回的結(jié)果,可以再次看成一張表去操作。
select 列名 from 表名 where 條件(子查詢操作替代一些值)
select 列名 from (子查詢的結(jié)果集) where 條件
5.11.1 子查詢作為查詢字段某個值
查詢薪資和Bruce工資一致的員工信息。
通過查詢可以得到Bruce的工資信息
再基于另一個查詢,將前面的Bruce的薪資結(jié)果作為條件判斷的一環(huán),從而實現(xiàn)利用子查詢得到結(jié)果
1、查詢Bruce的工資信息,返回 單列單行
select salary from t_employees where first_name = ‘Bruce’;
2、基于Bruce的工資信息查詢與其薪資一致的員工信息
select
*
from
t_employees
where
salary = (select salary from t_employees where first_name = 'Bruce');
5.11.2 子查詢作為 字段多值判斷的值
因為字段多值判斷是采用in的方式去做條件篩選。 一個字段需要多個值。
在利用子查詢時,應(yīng)當返回 單列多行 數(shù)據(jù)。
查詢last_name為King同一部門的員工信息
1、查詢last_name為King的部門信息。
select department_id from t_employees where last_name = ‘King’;
2、基于上述查詢返回的結(jié)果,查看同部門的員工信息
select
*
from
t_employees
where
department_id in (select department_id from t_employees where last_name = 'King');
5.11.3 子查詢作為 一張表操作。
可以直接基于子查詢返回的結(jié)果集做二次篩選。
查詢員工表中,工資排名前5名的員工。
這個查詢可以直接使用order by 排序,然后基于limit做篩選。
就為了使用,搞兩個SQL實現(xiàn),利用子查詢來玩。
1、查詢員工的信息,基于salary做降序排序。
select * from t_employees order by salary desc;
2、將上述的結(jié)果基于limit篩選出前5條。
select
*
from
(select * from t_employees order by salary desc) as temp
limit 5
5.11.4 子查詢的ALL、ANY(了解)
之前在給字段做=判斷時,子查詢必須返回單列單行的數(shù)據(jù),不然報錯。
其實在做=判斷時,即便返回了單列多行數(shù)據(jù),也可以采用ALL、ANY關(guān)鍵字解決問題。
查詢工資高于60部門員工的,所有人的信息。
select salary from t_employees where department_id = 60;
1、查詢比60部門所有員工薪資都高的員工信息。
select
*
from
t_employees
where
salary > ALL (select salary from t_employees where department_id = 60);
2、查詢比60部門任意一名員工薪資高的員工信息。
select
*
from
t_employees
where
salary > ANY (select salary from t_employees where department_id = 60);
5.12 合并查詢(了解)
將兩個select操作的結(jié)果整合為一個結(jié)果集返回。一般是為了規(guī)避掉一些查詢方式導致的效率較低,可以采用合并查詢來提升效率。
語法:select 列名 from 表名1 union select 列名 from 表名2; (會去重)
語法:select 列名 from 表名1 union all select 列名 from 表名2; (不會去重)
在使用union 或者 union all時,需要保證兩個select的列的個數(shù)是一致的。
哪怕兩次Select的列不是一個東西,但是個數(shù)一致,那就基于第一個select的列,作為返回的基準,將結(jié)果合并到一起。
5.13 表連接查詢
表連接可以將多張表關(guān)聯(lián)到一起,返回需要的內(nèi)容
語法:select 列名 from 表1 連接方式 表2 on 連接條件 連接方式 表3 on 連接條件 …………
內(nèi)連接語法: select 列名 from 表1 inner join 表2 on 連接條件
外連接:
左外連接:select 列名 from 表1 left [outer] join 表2 on 連接條件右外連接:select 列名 from 表1 right [outer] join 表2 on 連接條件
內(nèi)連接查詢操作。
內(nèi)連接查詢,針對哪些 連接條件 無法滿足的數(shù)據(jù),會直接篩選掉。
查詢當前員工名稱以及對應(yīng)的部門名稱。
# 顯示內(nèi)連接
select
e.first_name , e.last_name , d.department_name
from
t_employees as e
inner join t_departments as d on e.department_id = d.department_id;
# 隱示內(nèi)連接
select
e.first_name , e.last_name , d.department_name
from
t_employees e, t_departments d
where
e.department_id = d.department_id;
查詢員工的名稱,部門的名稱,部門所在國家的信息(三張表聯(lián)查)
# 查詢員工的名稱,部門的名稱,部門所在國家的信息(三張表聯(lián)查)
# 顯示內(nèi)連接
select
e.first_name , e.last_name ,d.department_name,l.city
from
t_employees e
inner join t_departments d on e.department_id = d.department_id
inner join t_locations l on l.location_id = d.location_id;
# 隱示內(nèi)連接
select
e.first_name , e.last_name ,d.department_name,l.city
from
t_employees e , t_departments d ,t_locations l
where
e.department_id = d.department_id
and d.location_id = l.location_id;
外連接查詢
還是基于前面玩的查詢,查詢當前員工名稱以及對應(yīng)的部門名稱。
因為之前用的內(nèi)連接的方式,導致一個員工
發(fā)現(xiàn),最后的部門Id是一個NULL,導致后續(xù)查詢時,并沒有這個員工的信息返回。
現(xiàn)在可以采用外鏈接的方式,來解決這個問題。
外鏈接前面說過左外的語法,和右外的語法。
其實就是將左邊的表,或者是右邊的表作為基準表,基準表回返回全部的數(shù)據(jù),無論連接條件是否滿足。
# 查詢當前 所有 員工名稱以及對應(yīng)的部門名稱。
select
e.first_name , e.last_name ,d.department_name
from
t_employees e left outer join t_departments d
on e.department_id = d.department_id;
注意,左外和右外是指定哪張表是基準表,基準表的數(shù)據(jù)會全部返回,匹配不到內(nèi)容的位置,會用NULL填充上。
5.14 常見錯誤
六、DML操作(重要)
關(guān)于DML,只需要保證可以完成三個操作即可。
6.1 新增(insert)
語法1:insert into 表名 (列1,列2,列3,列4…) values (值1,值2,值3,值4…);
語法2:insert into 表名 values (值1,值2,值3,值4…);
語法3:insert into 表名 (列1,列2,列3,列4…) values (值1,值2,值3,值4…),(值1,值2,值3,值4…)……;(批量添加)
MySQL中最長見的三個數(shù)據(jù)類型,數(shù)值,字符串,時間。
給t_jobs表添加一條數(shù)據(jù)。 記得確保前面給的列數(shù),和后面的值的個數(shù)需要保持一致。
# 給t_jobs表添加一條數(shù)據(jù)
insert into
t_jobs
(job_id,job_title,min_salary,max_salary)
values
('運營','運營',500,50000);
給t_employees表添加一條數(shù)據(jù),采用語法2的方式。 需要確保表中的所有字段的值都要給上。
針對時間類型數(shù)據(jù)的添加,在MySQL端可以直接輸入字符串的方式,MySQL可以幫助咱們做一些數(shù)據(jù)類型的轉(zhuǎn)換。
# 給t_employees表添加一條數(shù)據(jù),采用語法2的方式
insert into
t_employees
values
(100001,'張','三','123@123.com','18888888888','1999-11-11','程序員',5000,0.20,100,90);
給t_jobs表中基于一條SQL語句追加多行數(shù)據(jù)。而且可以看到受影響行數(shù)的信息。
insert into
t_jobs
(job_id,job_title,min_salary,max_salary)
values
('A','做A',5000,8000),
('B','做B',5000,8000),
('C','做C',5000,8000);
6.2 修改(update)
語法:update 表名 set 列1 = 新值1,列2 = 新值2 …… [where 條件];
正常修改語句從語法的角度講,可以不追加where條件,但是咱們再實際操作時, 一定要追加上條件,不然整張表都要被修改成一模一樣的數(shù)據(jù)。
修改job_id標識為A的數(shù)據(jù),將薪資最小和最大調(diào)整為3000,5000
update
t_jobs
set
min_salary = 3000,
max_salary = 5000
where
job_id = 'A';
如果返回的受影響行數(shù)為1,說明當前標識為A的這行數(shù)據(jù)發(fā)生了變化。
如果返回的受影響行數(shù)為0,不代表SQL執(zhí)行失敗,只是單純的這行數(shù)據(jù)沒變化。
6.3 刪除(delete)
語法:delete from 表名 [where 條件];
從刪除語句的語法來說,where條件可以不寫,但是如果不寫,就相當于清空了整張表。正常業(yè)務(wù)情況下是需要追加where。
將之前添加進去的測試數(shù)據(jù),全部都刪除
我這里是針對t_jobs和t_employees表追加了數(shù)據(jù),現(xiàn)在都干掉~
# 刪除t_jobs表中的,標識為A,B,C,程序員,運營這5條數(shù)據(jù)
delete from
t_jobs
where
job_id in ('A','B','C','程序員','運營');
# 刪除t_employees表中標識為100001,100002,100003,100004的員工信息干掉
delete from
t_employees
where
employee_id in (100001,100002,100003,'100004');
6.4 常見問題
七、數(shù)據(jù)表操作DDL操作
7.1 MySQL中的數(shù)據(jù)類型
7.1.1 數(shù)值類型
跟Java中的幾乎是一致的,但是比Java會更豐富一些,不過大類別依然是整形和浮點型
浮點型的數(shù)值中,所有的M,D,都必須保證M >= D
類型大小范圍描述tinyint1byte(-128~127)小整數(shù),映射Java中的Bytesmallint2byte…………小整數(shù),映射Java中的Shortint4byte…………默認整數(shù),映射Java中的Integerbigint8byte…………長整數(shù),映射Java中的Longfloat(10,2)4byte…………單精度浮點類型,映射Java中的Floatdouble(10,2)8byte…………雙精度浮點類型,映射Java中的Doubledecimal(M,D)看下面~…………映射Java中的BigDecimal
decimal存儲的空間大小:
每9位數(shù)最多占用4字節(jié),整數(shù)和小數(shù)要分開算,如果小于9位數(shù),基于下述表格計算
位數(shù)大小001–213–425–637–94
如果指定的 DECIMAL(18,9),這個數(shù)值是小數(shù)點前,占用4字節(jié),小數(shù)點后,也占用4字節(jié)。一共占用8字節(jié)。
如果指定的 DECIMAL(20,6),這個數(shù)值是小數(shù)點前有14位,9位占用4子節(jié),剩下5位占用3字節(jié)。小數(shù)點后的6位,占用3字節(jié)。一共占用10字節(jié)。
7.1.2 時間類型
MySQL中的時間類型比Java中要豐富一些。Java中有Date,LocalDate之類的,MySQL相對更多一些。
類型大小范圍格式描述date3byte用到死!yyyy-MM-dd存儲日期time3byte夠用!HH:mm:ss存儲時間datetime8byte用到死!yyyy-MM-dd HH:mm:ss存儲日期和時間timestamp4byte1970-01-01 00:00:00~2038-01-19 03:14:07yyyy-MM-dd HH:mm:ss存儲日期和時間
datetime和timestamp的區(qū)別:
存儲的大小不一樣。
datetime占用8字節(jié)。timestamp占用4字節(jié)。 存儲的范圍不一樣。
datetime可以持續(xù)到9999年。timestamp是從1970年~2038年。 存儲的時區(qū)問題。
datetime存儲時,不考慮時區(qū),存儲什么就是什么,取的時候也就是什么。timestamp存儲時,會將時間從當前時區(qū)轉(zhuǎn)換為UTC進行存儲,查詢時,將其再轉(zhuǎn)換為當前客戶端的時區(qū)。
其次,在5.6.5版本后,datetime和timestamp對于行級數(shù)據(jù)變化,自動更新為當前系統(tǒng)時間,都是支持的。(后面創(chuàng)建表會演示這個操作)
7.1.3 字符串類型
MySQL中的字符串類型那就多了,Java中就String。
類型描述char(長度)定長字符串varchar(長度)變長字符串text大文本類型blob以二進制的形式存儲大文本數(shù)據(jù)
char和varchar核心區(qū)別:
char指定好長度后,無論存儲多少數(shù)據(jù),就占這個長度的大小。varchar指定好長度后,你寫入了多大的數(shù)據(jù),他就占用多少大小。
7.2 創(chuàng)建表
創(chuàng)建表的語法:
create table 表名(
列名 數(shù)據(jù)類型 [約束],
列名 數(shù)據(jù)類型 [約束],
…………
列名 數(shù)據(jù)類型 [約束] -- 最后一行不要在后面追加逗號
);
創(chuàng)建一張學生表,student。表名和列名如果存在多個單詞,用_分開,不要出現(xiàn)大寫字母。
列名數(shù)據(jù)類型約束描述student_idbigint無學員編碼student_namevarchar(32)無學員名稱student_genderchar(1)無學員性別student_birthdaydate無學員生日
創(chuàng)建學生表的SQL語句
create table student(
student_id bigint comment '學員編號',
student_name varchar(32) comment '學員名稱',
student_gender char(1) comment '學員性別',
student_birthday date comment '學員生日'
)comment '學生表';
Ps:如果構(gòu)建完之后,通過Navicat查看注釋信息時,發(fā)現(xiàn)有亂碼,需要設(shè)置系統(tǒng)的一些內(nèi)容,如果沒亂碼,你不需要做任何事情?。。。?/p>
1、打開cmd,輸入chcp,如果是936,那就開始設(shè)置當前操作系統(tǒng)的語言
2、更改系統(tǒng)區(qū)域設(shè)置
3、修改完畢后,需要重啟電腦才可以生效!! 可以在重啟后,再次打開cmd,查看chcp的返回內(nèi)容
7.3 表的其他操作(了解)
語法:alter table 表名 操作
7.3.1 添加一個列
語法:alter table 表名 add 列名 類型;
給student表追加一個student_phone的列。類型是varchar(16)
# 添加一列
alter table
student
add
student_phone varchar(16);
7.3.2 修改表中的列
語法:alter table 表名 modify 列名 類型;
將student表中的student_phone的列中的varchar長度設(shè)置為11。
# 修改一列
alter table
student
modify
student_phone varchar(11) comment '學生手機號';
7.3.3 刪除表中的列
語法:alter table 表名 drop 列名;
將前面用navicat隨便添加的列刪掉。刪除ssss這個列。
# 刪除一列
alter table
student
drop
ssss;
7.3.4 修改表名
語法:alter table 表名 rename 新表名;
將student表修改為table_student
# 修改表名
alter table
student
rename
table_student;
7.3.5 修改列名和類型
語法:alter table 表名 change 舊列名 新列明 類型;
將table_student表中的student_gender修改為student_sex,并且類型指定為tinyint
# 修改列的名稱和類型
alter table
table_student
change
student_gender
student_sex tinyint;
7.3.6 清空表數(shù)據(jù)
這個操作的語法跟前面完全不同。單獨的語法。
這個清空表不是單獨的刪除數(shù)據(jù),而是直接將表摧毀掉,再重新創(chuàng)建一張一模一樣的表。
語法:truncate 表名;
直接將table_student中的數(shù)據(jù)直接干掉。
# 摧毀表,重新創(chuàng)建
truncate table_student;
7.3.7 刪除表
這個跟前面的操作也不一樣。
語法:drop table 表名;
刪除table_student表。
drop table table_student;
7.4 常見問題
八、約束
問題:往一張表中插入完全一致的數(shù)據(jù),可行不。
從功能的維度來說,完全沒有問題。但是從業(yè)務(wù)方向來考慮,兩個完全一模一樣的數(shù)據(jù)沒有什么意義。
從行數(shù)據(jù)的維度來考慮,需要保證 實體完整性約束 。需要確保每行數(shù)據(jù)不重復,數(shù)據(jù)唯一。
8.1 主鍵約束(重要)
primary key 主鍵的約束,標識表中的一行數(shù)據(jù),當前指定的主鍵列的 值不可以重復,并且不能為NULL
主鍵在表中只能值有一個,指定多個主鍵,就會報錯。
create table student(
student_id bigint primary key comment '學員編號' ,
student_name varchar(32) comment '學員名稱',
student_gender char(1) comment '學員性別',
student_birthday date comment '學員生日'
)comment '學生表';
insert into
student
values
(1,'李四','男','2001-11-11');
Ps:一般咱們推薦給表添加一個主鍵約束,一般情況下,可以針對有意義數(shù)據(jù)設(shè)置主鍵約束,也可以單獨搞一個列來作為主鍵(推薦是有序自增的最好)
這里推薦主鍵最好是自增的,這樣后期在做一些范圍查詢的時候效率會更好。
現(xiàn)在student_id是主鍵,每次咱們需要自己指定1,2,3,4,5,6,7…………很麻煩。
可以給主鍵設(shè)置一個自動增長的效果。
auto_increment 放在約束后面即可,就配合主鍵使用,其他列不用。
create table student(
student_id bigint primary key auto_increment comment '學員編號' ,
student_name varchar(32) comment '學員名稱',
student_gender char(1) comment '學員性別',
student_birthday date comment '學員生日',
student_phone varchar(11) unique comment '學員手機號'
)comment '學生表';
insert into
student
values
(NULL,'李四','男','2001-11-12','18888888855');
8.2 唯一約束
unique 唯一約束。標識表中的一行數(shù)據(jù),當前指定的唯一約束的列的 值不允許重復,可以為NULL
唯一約束可以在一張表中指定多個列。
允許為NULL,并且,多個NULL可以同時存在。
create table student(
student_id bigint primary key comment '學員編號' ,
student_name varchar(32) comment '學員名稱',
student_gender char(1) comment '學員性別',
student_birthday date comment '學員生日',
student_phone varchar(11) unique comment '學員手機號'
)comment '學生表';
insert into
student
values
(1,'李四','男','2001-11-12','18888888888');
域完整性約束:限制列的數(shù)據(jù)完整性。
8.3 非空約束
not null ,在列的后面指定上這個約束即可。
給學生生日指定為非空!
create table student(
student_id bigint primary key auto_increment comment '學員編號' ,
student_name varchar(32) comment '學員名稱',
student_gender char(1) comment '學員性別',
student_birthday date not null comment '學員生日',
student_phone varchar(11) unique comment '學員手機號'
)comment '學生表';
insert into
student
values
(NULL,'王五','男',NULL,'18888888434');
8.4 默認值約束
default 默認值 ,當前列如果沒有指定任何的值,會采用這個默認值填充。
給學員名稱列設(shè)置默認值,如果沒指定姓名就叫 ‘張三’。
測試默認值時,需要采用下述方式使用insert語句,跳過student_name字段的賦值。
create table student(
student_id bigint primary key auto_increment comment '學員編號' ,
student_name varchar(32) default '張三' comment '學員名稱',
student_gender char(1) comment '學員性別',
student_birthday date not null comment '學員生日',
student_phone varchar(11) unique comment '學員手機號'
)comment '學生表';
drop table student;
insert into
student
(student_gender,student_birthday,student_phone)
values
('男','2011-11-11','18888888433');
8.5 檢查約束
check (檢查約束要求) ,這個是MySQL8.x提供的約束功能,約束某一個列的值滿足一定的條件要求
給student表中的性別字段,指定一個檢查約束,要求添加的值只能是男、女。不允許添加其他內(nèi)容。
-- 是單獨指定約束信息
create table student(
student_id bigint primary key auto_increment comment '學員編號' ,
student_name varchar(32) default '張三' comment '學員名稱',
student_gender char(1) comment '學員性別',
student_birthday date not null comment '學員生日',
student_phone varchar(11) unique comment '學員手機號',
constraint student_gender_check check (student_gender = '男' or student_gender = '女')
)comment '學生表';
-- 在字段后直接編寫。
create table student(
student_id bigint primary key auto_increment comment '學員編號' ,
student_name varchar(32) default '張三' comment '學員名稱',
student_gender char(1) check (student_gender = '男' or student_gender = '女') comment '學員性別',
student_birthday date not null comment '學員生日',
student_phone varchar(11) unique comment '學員手機號'
)comment '學生表';
-- 測試
insert into
student
(student_gender,student_birthday,student_phone)
values
('彎','2011-11-11','18888888435');
8.6 數(shù)值的約束
UNSIGNED,數(shù)值的約束,保證這個數(shù)值必須是正數(shù),不允許存儲負數(shù)。
同時取值范圍還可以增加接近一倍。
比如tinyint,存儲范圍是-128到127,如果追加上了UNSIGNED,就可以標識0到255。
# 添加unsigned約束后,數(shù)值就不允許存儲負數(shù)了。
create table yyy(
id tinyint unsigned
);
insert into yyy values (-1);
zerofill,根據(jù)指定的數(shù)值長度,如果當前數(shù)值的長度不滿足指定的長度,會自動在前面填充0。
可以在數(shù)值類型后面追加這個約束。
8.7 常見錯誤
九、事務(wù)(重要)
9.1 轉(zhuǎn)賬操作
生活當眾,轉(zhuǎn)賬是從一方扣錢,另一方加錢,采用數(shù)據(jù)庫來模擬一下這個操作。
優(yōu)先準備好轉(zhuǎn)賬的環(huán)境。
# 創(chuàng)建一個賬戶表
create table account(
id bigint primary key auto_increment comment '賬戶標識',
name varchar(16) not null comment '賬戶名稱',
money bigint not null comment '賬戶余額'
)comment '賬戶表';
# 添加兩個賬戶信息,張三、李四,一人1000大洋
insert into
account
(name,money)
values
('張三',1000),('李四',1000);
# 模擬張三給李四轉(zhuǎn)500大洋
update account set money = money - 500 where id = 1;
update account set money = money + 500 where id = 2;
轉(zhuǎn)賬分為兩個操作,需要先給一個用戶扣錢,再給一個用戶加錢。
第一個扣錢的操作成功了,但是因為一些其他的原因,比如服務(wù)器斷點,或者是一些異常情況,導致第二個加錢的SQL執(zhí)行失敗。整個轉(zhuǎn)賬的業(yè)務(wù)其實是失敗的,但是第一個的錢扣了,沒了。。。。。
正常應(yīng)當是,這 兩個操作要么都執(zhí)行成功,要么都執(zhí)行失敗。
上述的轉(zhuǎn)賬問題,咱們就可以基于事務(wù)來解決。
事務(wù)可以看做是一個最小的執(zhí)行單位,一個事務(wù)可以由一條或者多條SQL語句組成。 一個事務(wù)操作,所有的SQL語句要么都執(zhí)行成功,要么都執(zhí)行失敗。
9.2 事務(wù)操作
首先MySQL他模式就是開啟事務(wù)的,但是這個事務(wù)每執(zhí)行一個DML語句,都會自動的提交結(jié)束。
通過幾個操作來實現(xiàn)自己對事務(wù)的控制。
開啟事務(wù):
1、因為MySQL默認自動結(jié)束事務(wù)的,咱們可以自己關(guān)閉這種自動結(jié)束的操作。
2、也可以通過單獨的指令,來指定事務(wù)開始和結(jié)束的位置。
set AutoCommit = 0; -- 默認情況,值是1,代表每次自動結(jié)束事務(wù),設(shè)置為0,代表需要咱們手動的結(jié)束事務(wù)。
begin; -- 開啟手動結(jié)束事務(wù)操作,需要在執(zhí)行完SQL語句后,自己去執(zhí)行結(jié)束事務(wù)的指令
start transaction; -- 跟begin是一樣的。。。。
結(jié)束事務(wù):
1、如果開啟事務(wù)的所有SQL語句,執(zhí)行沒有問題,可以直接提交事務(wù)。
2、如果開啟事務(wù)后執(zhí)行的SQL語句存在問題,可以執(zhí)行回滾事務(wù)操作。
commit; -- 提交事務(wù),事務(wù)中的操作都會落到磁盤當眾
rollback; -- 回滾事務(wù),事務(wù)中的操作全部都會恢復到事務(wù)開啟之前的狀態(tài)。
將前面的轉(zhuǎn)賬操作,基于事務(wù)控制,解決前面的問題。
# 模擬張三給李四轉(zhuǎn)500大洋
set AutoCommit = 1; -- 關(guān)閉自動結(jié)束事務(wù),需要遇到commit或者rollback才會結(jié)束這個事務(wù)
begin; -- 手動開啟了一個事務(wù),需要遇到commit或者rollback才會結(jié)束這個事務(wù)。
start transaction; -- 也是手動開啟一個事務(wù)。
update account set money = money - 500 where id = 1;
update account set money = money + 500 where id = 2;
commit;
rollback;
-- 事務(wù)結(jié)束有兩種方式。commit,提交。 rollback,回滾。
9.3 事務(wù)的基本實現(xiàn)原理
9.4 事務(wù)的特性
原子性(Atomicity) 事務(wù)是一個最小的執(zhí)行單位,一次事務(wù)的操作要么都成功,要么都失敗。一致性(Consistency) 表示一個事務(wù)內(nèi)有一個操作失敗時,所有的更改過的數(shù)據(jù)都必須回滾到修改前的狀態(tài)。隔離性(Isolation) 事務(wù)查看數(shù)據(jù)操作時數(shù)據(jù)所處的狀態(tài),要么是另一個并發(fā)事務(wù)修改之前的狀態(tài),要么是另一個事務(wù)修改它之后的狀態(tài),事務(wù)不會查看中間狀態(tài)的數(shù)據(jù)。持久性(Durablility) 事務(wù)正常提交后,會將數(shù)據(jù)落到磁盤中,影響是永久了。
9.5 事務(wù)并發(fā)問題
臟讀:一個事務(wù)中,讀取到了另一個事務(wù)未提交的數(shù)據(jù)。(這個問題必須要解決)不可重復讀:一個事務(wù)中,多次查詢同一個數(shù)據(jù),結(jié)果不一致。原因是其他事務(wù)中對這個數(shù)據(jù)修改了,并且提交事務(wù)了?;米x:一個事務(wù)中,多次查詢同一個數(shù)據(jù),結(jié)果不一致。原因是其他事務(wù)中對某個數(shù)據(jù)進行了增刪,并且提交事務(wù)了。
為了復現(xiàn)上述的問題,優(yōu)先將MySQL的事務(wù)隔離級別調(diào)低
-- 為了查看到所有問題的效果,這里優(yōu)先將事務(wù)的隔離級別設(shè)置為最低等級。READ-UNCOMMITTED。
set global transaction_isolation = 'READ-UNCOMMITTED';
-- 因為設(shè)置的是全局的事務(wù)隔離級別,設(shè)置完畢后,關(guān)閉連接,重新打開,才會生效。
select @@transaction_isolation;
復現(xiàn)臟讀效果:
復現(xiàn)不可重復讀效果:
復現(xiàn)幻讀的效果:
9.6 事務(wù)的隔離級別
事務(wù)的隔離級別就是用來解決前面9.5聊到的事務(wù)并發(fā)的三個問題的。
READ-UNCOMMITTED(讀未提交):可以讀取到未提交事務(wù)的數(shù)據(jù)。
(一個問題都不能解決) READ-COMMITTED(讀已提交):可以讀取到已經(jīng)提交事務(wù)的數(shù)據(jù)。
(只能解決臟讀)Oracle默認隔離級別是READ-COMMITTED REPEATABLE-READ(可重復讀):會讓一次事務(wù)多次查詢同一數(shù)據(jù)結(jié)果一致(修改導致)。
(可以解決臟讀和不可重讀)MySQL默認隔離級別是可重復讀REPEATABLE-READ SERIALIZABLE(串行化):上鎖,所有問題都能解決。
(可以解決所有問題)
為了解決上面說道的各種問題,這里可以設(shè)置事務(wù)的隔離級別,然后查看效果
查看事務(wù)的隔離級別的方式:
select @@transaction_isolation;
設(shè)置事務(wù)的隔離級別,可以設(shè)置全局的,也可以針對當前連接設(shè)置。
-- 全局的事務(wù)隔離級別設(shè)置。(設(shè)置完,需要關(guān)閉連接,重新打開)
set global transaction_isolation = 'SERIALIZABLE';
-- 當前會話的事務(wù)隔離級別設(shè)置。
set session transaction_isolation = 'SERIALIZABLE';
十、權(quán)限控制DCL操作(了解)
DCL就是Data Control Language,一般就是對于用戶的權(quán)限做一些授權(quán)操作之類的內(nèi)容。 直接構(gòu)建用戶,基于用戶操作對應(yīng)庫表的權(quán)限。
10.1 用戶的操作
創(chuàng)建用戶: create user 用戶名@IP地址 identified by 密碼;
這里的IP地址,是指定Host列,也就是當前用戶可以基于哪個IP地址連接當前MySQL
創(chuàng)建一個用戶,用戶名是zheng,密碼是zheng,采用默認的IP,%。
#創(chuàng)建一個用戶,用戶名是zheng,密碼是zheng。
create user 'zheng' identified by 'zheng';
create user 'zhang'@'%' identified by 'zhang';
刪除用戶:drop user 用戶名;
刪除上面的用戶zhang。
# 刪除上面的用戶zhang。
drop user 'zhang';
Ps:創(chuàng)建完畢的用戶,密碼插件默認是caching_sha2_password,正常黑窗口是可以連接的。我提供的Navicat版本比較低,所以無法連接,需要將密碼插件修改為mysql_native_password。
10.2 授權(quán)
給用戶賦予操作指定庫和表的權(quán)限。
語法:grant all on 庫名.表名 to 用戶名;
all代表賦予這個庫和表的所有操作權(quán)限。
庫名和表名如果想賦予全部的,使用*代替。
賦予zheng用戶,可以操作test庫下所有表的所有操作權(quán)限。
# 賦予zheng用戶,可以操作test庫下所有表的所有操作權(quán)限。
grant all on test.* to 'zheng';
發(fā)現(xiàn)賦予權(quán)限后,依然無法連接,原因是zheng用戶默認的密碼插件是caching_sha2_password。咱們的Navicat版本低,無法識別,通過alter語句修改一下插件信息
alter user 'zheng'@'%' identified with mysql_native_password by 'zheng';
正常連接后,可以看到具體的賦予權(quán)限的庫表信息。
10.3 撤銷授權(quán)
將前面賦予的權(quán)限撤銷掉。
語法:revoke all on 庫名.表名 from 用戶名;
撤銷掉對zheng用戶賦予的test庫中所有表的所有權(quán)限
# 撤銷掉對zheng用戶賦予的test庫中所有表的所有權(quán)限
revoke all on test.* from 'zheng';
十一、視圖(了解)
11.1 視圖介紹
視圖(View),是一張?zhí)摂M表,在本地磁盤是沒有存儲的。
視圖是從一張表或者多張表中查詢出來的結(jié)果,作用和真實的表是一樣的,包含一系列帶有行和列的數(shù)據(jù)。
在視圖中,用戶可以通過select語句查詢視圖里的數(shù)據(jù),也可以基于insert,update,delete按修改視圖的數(shù)據(jù),但是修改視圖的本質(zhì)就是在修改原始表。一般不允許做修改視圖的操作。
視圖的核心作用是可以將一些非常復雜的查詢邏輯封裝到一個視圖里,同時也可以將一些敏感數(shù)據(jù)規(guī)避。
視圖的本質(zhì),就是一個SQL。
11.2 視圖語法
構(gòu)建視圖語法:create view 視圖名 as (查詢語句);
視圖的構(gòu)建很簡單,只要有對應(yīng)的查詢語句即可。
但是記住,視圖無法提升你的查詢效率,視圖的本質(zhì)就是一個查詢語句。
視圖的出現(xiàn)是為了剛方便咱們的操作。。
11.3 視圖構(gòu)建
將之前玩的employee表中薪資大于5000的信息數(shù)據(jù)封裝為一個視圖
薪資大于5000,就是where salary > 5000。
查詢SQL搞定,直接封裝視圖即可。
# 將之前玩的employee表中薪資大于5000的信息數(shù)據(jù)封裝為一個視圖
select * from t_employees where salary > 5000;
# 構(gòu)建為視圖
create view v_emp_salary_gt_fivethousand as (select * from t_employees where salary > 5000);
11.4 視圖使用
視圖的使用和正常操作表是一樣的。
前面構(gòu)建好的v_emp_salary_gt_fivethousand就可以直接查詢
# 查詢視圖
select first_name,last_name from v_emp_salary_gt_fivethousand;
視圖是可以修改的,但是修改的不是視圖,修改的是視圖映射的原表數(shù)據(jù)。
Ps:能改,但是別改。記住,視圖就是用來查詢的,別用于寫操作。
11.5 刪除視圖
刪除視圖跟刪除表一樣。
語法:drop view 視圖名;
# 刪除視圖
drop view v_emp_salary_gt_fivethousand;
十二、同義詞(了解)
MySQL不支持同義詞synonym這個關(guān)鍵字。
Oracle中支持synonym的構(gòu)建。
在Oracle中是給對應(yīng)的表,視圖,存儲過程起個別名,訪問起來更方便一些。
因為在MySQL8.0中,提供了一個構(gòu)建同義詞數(shù)據(jù)庫的存儲函數(shù)。
將一些名字比較惡心的數(shù)據(jù)庫,起個別名,用于做一些查詢操作。
語法:call sys.create_synonym_db(‘原庫’,‘同義詞庫’);
# 給test庫搞一個同義詞
call sys.create_synonym_db('test','t');
構(gòu)建完畢之后,會出現(xiàn)一個t數(shù)據(jù)庫,在t數(shù)據(jù)庫中,會將test庫中的所有表和視圖,全部生成為視圖存戶到t庫中。
構(gòu)建完畢同義詞庫中的視圖,如果你做了修改和刪除數(shù)據(jù)的操作,那修改和刪除的是原庫中的數(shù)據(jù)。
不過刪除視圖無所謂,視圖刪除了,和原表沒關(guān)系。
十三、索引
索引可以提升查詢是的效率。(合理的運用)
索引是給表中具體的列追加一個索引。
索引并不是什么列都適合添加的。
一般需要對經(jīng)常被查詢的列添加索引,而且這個列的值不能過于重復。如果列的長度特別大的就不太適合添加索引。
查看表中的索引信息。
語法:show index from 表名;
通過上述語句,查看一下t_employees表中的索引信息
添加索引信息
語法:create [索引類型] index 索引名稱 on 表名(列);
給員工表中的手機號字段,追加上一個普通索引。
# 給員工表中的手機號字段,追加上一個普通索引。
create index index_emp_phone on t_employees(phone_number);
給員工表中的郵箱字段追加一個唯一索引。
# 給員工表中的郵箱字段追加一個唯一索引。
create unique index index_unique_emp_email on t_employees(email);
經(jīng)常有一種操作,在查詢某張表時,經(jīng)常用這種條件where a = ? and b = ? ……
這種查詢可以做一個優(yōu)化,可以將a列和b列創(chuàng)建一個聯(lián)合(復合、多列)索引。
語法:create [索引類型] index 索引名稱 on 表名(列1,列2);
這種聯(lián)合索引的查詢效率,比起單獨給列1和列2分別構(gòu)建索引的查詢效率要快。
將員工表中的first_name和last_name組合一個聯(lián)合索引。
# 將員工表中的first_name和last_name組合一個聯(lián)合索引。
create index index_emp_name on t_employees(first_name,last_name);
刪除索引操作。
語法:drop index 索引名稱 on 表;
將員工表中的email的唯一索引刪除掉。
# 將員工表中的email的唯一索引刪除掉。
drop index index_unique_emp_email on t_employees;
創(chuàng)建表的時候,也可以指定索引信息(了解一小下)
語法:
create table 表名(
列1 數(shù)據(jù)類型…………,
index(列名) # 構(gòu)建索引的方式
);
十四、綜合練習
后期針對MySQL的操作,其實90%以上都是做Select查詢操作。
現(xiàn)在就用Oracle提供的三張經(jīng)典表來做練習
emp(員工表)、dept(部門表)、salgrade(工資等級表)
14.1 外鍵約束的補充(了解)
在做真正的練習之前,優(yōu)先搞定一下之前一致沒聊的外鍵約束。
外鍵其實就是做表與表之前關(guān)聯(lián)的一個約束。
現(xiàn)在有員工表,也有部門表。
一個部門下可以有多個員工。一個員工只能屬于一個部門。
就需要在一得一方,也就是員工表中,有一個外鍵,也就是deptno這個列,他的作用是和dept部門表做一個關(guān)聯(lián)。當然,也可以給這個員工表中的deptno追加一個外鍵約束(不推薦)。
也給emp額外追加上外鍵約束。
語法:alter table 表名1 add constraint 外鍵名稱 foreign key (列1) references 表名2(列2);
# 給員工表追加上deptno的外鍵約束
alter table emp add constraint fk_emp_dept foreign key (deptno)
references dept(deptno);
14.2 查詢操作練習
14.2.1 查詢每個部門最高薪水的人員名稱
需要查詢的內(nèi)容都處于員工表中。
需要查詢員工的名稱,部門,薪資。
首先先完成查詢每個部門的最高薪資。 需要利用聚合函數(shù)的max,并且對部門編號做一個分組。
然后將部門最高信息查詢返回的虛擬表與emp表做表連接,查詢出最終結(jié)果
# 首先先完成查詢每個部門的最高薪資。 需要利用聚合函數(shù)的max,并且對部門編號做一個分組。
select deptno,max(sal) as maxsal from emp group by deptno;
# 將前面查詢到的部門最高薪資,和當前的emp表做一個表連接操作,查詢出每個部門薪資最高的員工名稱
select
e.ename,e.deptno,m.maxsal
from
emp e inner join (select deptno,max(sal) as maxsal from emp group by deptno) m
on e.deptno = m.deptno and e.sal = m.maxsal;
14.2.2 查詢哪些員工薪資在部門的平均薪資之上
首先,依然還是在員工表中查詢。
需要查詢員工名稱,員工薪資,部門編號,部門平均薪資
首先需要先將各個部門的平均薪資查詢出來,根據(jù)聚合函數(shù)avg以及對部門編號分組查詢。
然后將查詢的平均薪資和員工表做一個關(guān)聯(lián)。
-- 查詢哪些員工薪資在部門的平均薪資之上
-- 需要查詢員工名稱,員工薪資,部門編號,部門平均薪資
# 首先需要先將各個部門的平均薪資查詢出來,根據(jù)聚合函數(shù)avg以及對部門編號分組查詢。
select deptno,avg(sal) avgsal from emp group by deptno;
# 將員工表和上述查詢部門平均薪資的表關(guān)聯(lián)到一起,條件是部門編號一致 and 員工薪資大于平均薪資
select
e.ename,e.sal,e.deptno,a.avgsal
from
emp e inner join (select deptno,avg(sal) avgsal from emp group by deptno) a
on e.deptno = a.deptno and e.sal > a.avgsal;
14.2.3 查詢每個部門的平均薪資等級
首先這里需要查詢員工表和薪資等級表。
需要查詢部門編號以及部門的平均薪資等級
首先需要查詢所有員工的薪資等級是多少。
直接將上述的查詢結(jié)果作為一個from的虛擬表,直接對部門做分組,針對薪資等級做avg平均值即可
-- 查詢每個部門的平均薪資等級
-- 需要查詢部門編號以及部門的平均薪資等級
# 首先需要查詢所有員工的薪資等級是多少。
select
e.deptno,s.grade
from
emp e inner join salgrade s
on e.sal between s.losal and hisal
# 可以將上述的查詢結(jié)果,基于deptno做分組,然后將grade做一個avg算平均數(shù)。
select
es.deptno,avg(es.grade)
from
(select e.deptno,s.grade from emp e inner join salgrade s on e.sal between s.losal and hisal) es
group by deptno;
14.2.4 查詢平均薪資最高的部門名稱
首先需要查詢員工表和部門表
需要查詢出來部門的名稱和平均薪資
首先平均薪資單獨的emp表就可以查詢出來,再基于排序和limit,就可以只查詢出平均薪資最高的部門
然后將上述查詢結(jié)果的內(nèi)容,和dept表做表連接,查詢出薪資最高的部門信息
-- 查詢平均薪資最高的部門名稱
-- 需要查詢出來部門的名稱和平均薪資
# 首先平均薪資單獨的emp表就可以查詢出來,再基于排序和limit,就可以只查詢出平均薪資最高的部門
select deptno,avg(sal) as avgsal from emp group by deptno order by avgsal desc limit 1
# 基于上述查詢的結(jié)果,和dept表做一個表連接操作
select
d.dname,da.avgsal
from
dept d inner join (select deptno,avg(sal) as avgsal from emp group by deptno order by avgsal desc limit 1) da
on d.deptno = da.deptno;
上述SQL可以查詢出emp,dept表中的正確結(jié)構(gòu),但是如果多個部門的平均薪資一致,并且都是最高薪資,那上述查詢就有問題了。
上述的limit方式不太合適了。
第一步:查詢出平均薪資的最大值。
第二步:查詢出和平均薪資最大值一致的部門編號。
第三部:基于部門編號查詢出部門的名稱。
# 上述的limit看著不錯,但是存在問題。
# 第一步:查詢出平均薪資的最大值。
select avg(sal) as avgsal from emp group by deptno order by avgsal desc limit 1;
# 第二步:查詢出和平均薪資最大值一致的部門編號。
select deptno,avg(sal) as maxavgsal from emp group by deptno having maxavgsal = (select avg(sal) as avgsal from emp group by deptno order by avgsal desc limit 1);
# 第三部:基于部門編號查詢出部門的名稱。
select
d.dname,avg(sal) as maxavgsal
from emp e inner join dept d on e.deptno = d.deptno
group by d.dname
having maxavgsal = (select avg(sal) as avgsal from emp group by deptno order by avgsal desc limit 1);
14.2.5 查詢薪水比自己領(lǐng)導還高的員工信息。
首先需要查詢emp表,但是需要兩張emp一個作為普通員工信息,一個作為領(lǐng)導信息
查詢員工名稱和員工薪資,領(lǐng)導名稱和領(lǐng)導薪資
直接將兩張emp表做連接,連接的條件是員工表中的mgr,與領(lǐng)導表中的empno作為條件。
-- 查詢薪水比自己領(lǐng)導還高的員工信息。
-- 查詢員工名稱和員工薪資,領(lǐng)導名稱和領(lǐng)導薪資
# 直接將兩張emp表做連接,連接的條件是員工表中的mgr,與領(lǐng)導表中的empno作為條件。
select
e.ename,e.sal,me.ename,me.sal
from
emp e inner join emp me on e.mgr = me.empno
where
e.sal > me.sal;
14.2.6 查詢比普通員工的最高薪資還要高的領(lǐng)導名稱
首先查詢的依然是emp表。
查詢出領(lǐng)導的名稱和薪資即可。
要先分出來哪些是普通員工,哪些是領(lǐng)導。 領(lǐng)導的empno都在mgr字段上。
分成三步查詢。
1、先查詢出所有的領(lǐng)導的empno,只需要查詢mgr字段即可,做個去重。
2、再基于上面查詢出來的領(lǐng)導的empno,篩選出普通員工,查詢出普通員工中的最高薪資。
3、再查詢領(lǐng)導信息,薪資大于普通員工的最高薪資的領(lǐng)導信息查詢出來。
-- 查詢比普通員工的最高薪資還要高的領(lǐng)導名稱
-- 1、先查詢出所有的領(lǐng)導的empno,只需要查詢mgr字段即可,做個去重。
select distinct mgr from emp where mgr is not null;
-- 2、再基于上面查詢出來的領(lǐng)導的empno,篩選出普通員工,查詢出普通員工中的最高薪資。
select max(sal) as maxsal from emp where empno not in (select distinct mgr from emp where mgr is not null);
-- 3、再查詢領(lǐng)導信息,薪資大于普通員工的最高薪資的領(lǐng)導信息查詢出來。
select
ename,sal
from
emp
where
empno in (select distinct mgr from emp where mgr is not null)
and sal > (select max(sal) as maxsal from emp where empno not in (select distinct mgr from emp where mgr is not null));
14.2.7 查詢每個薪資等級有多少個員工
首先必然需要查詢員工表以及薪資等級表的關(guān)聯(lián)操作。
查詢出薪資等級和對應(yīng)的員工個數(shù)即可。
分成兩步操作:
1、先基于emp和salgrade表查詢出每位員工的薪資等級
2、在上述的基礎(chǔ)上,再根據(jù)grade字段進行分組,查詢count即可。
-- 查詢每個薪資等級有多少個員工
# 1、先基于emp和salgrade表查詢出每位員工的薪資等級
select
e.ename,s.grade
from
emp e inner join salgrade s on e.sal between s.losal and s.hisal;
# 2、在上述的基礎(chǔ)上,再根據(jù)grade字段進行分組,查詢count即可。
select
s.grade,count(1)
from
emp e inner join salgrade s on e.sal between s.losal and s.hisal
group by s.grade
order by s.grade;
14.2.8 查詢出入職時間早于其領(lǐng)導的員工信息和部門信息
首先需要查詢emp表兩張,同時還要查詢出對應(yīng)的部門信息,還要關(guān)聯(lián)部門表。
需要查詢出員工名稱,部門名稱,領(lǐng)導名稱,領(lǐng)導部門
分成兩步操作:
1、查詢出員工及其領(lǐng)導信息,并且追加上一個判斷,員工的入職時間,要早于領(lǐng)導的入職時間
2、再上述的基礎(chǔ)上,再額外關(guān)聯(lián)兩張部門表,查詢出對應(yīng)的部門名稱即可。
-- 查詢出入職時間早于其領(lǐng)導的員工信息
# 需要查詢出員工名稱,部門名稱,領(lǐng)導名稱,領(lǐng)導部門
# 1、查詢出員工及其領(lǐng)導信息,并且追加上一個判斷,員工的入職時間,要早于領(lǐng)導的入職時間
select
e.ename 員工名稱,m.ename 領(lǐng)導名稱
from
emp e inner join emp m on e.mgr = m.empno
where
e.hiredate < m.hiredate;
# 2、再上述的基礎(chǔ)上,再額外關(guān)聯(lián)兩張部門表,查詢出對應(yīng)的部門名稱即可。
select
e.ename 員工名稱,d.dname 員工部門,m.ename 領(lǐng)導名稱 ,md.dname 領(lǐng)導部門
from
emp e inner join emp m on e.mgr = m.empno
inner join dept d on e.deptno = d.deptno
inner join dept md on m.deptno = md.deptno
where
e.hiredate < m.hiredate;
14.2.9 查詢出至少有5位員工的部門信息
首先需要查詢emp和dept表,需要兩張表做一個關(guān)聯(lián)。
需要查詢部門的編號,部門的名稱,部門的員工人數(shù)。
分成兩步走:
1、關(guān)聯(lián)員工和部門表,查詢出部門信息和部門的員工人數(shù)。
2、在上述的基礎(chǔ)上,篩選出員工人數(shù)大于5個的部門信息。
-- 查詢出至少有5位員工的部門信息
# 需要查詢部門的編號,部門的名稱,部門的員工人數(shù)。
# 分成兩步走:
# 1、關(guān)聯(lián)員工和部門表,查詢出部門信息和部門的員工人數(shù)。
select
d.deptno,d.dname,count(1)
from
emp e inner join dept d on e.deptno = d.deptno
group by d.deptno;
# 2、在上述的基礎(chǔ)上,篩選出員工人數(shù)大于5個的部門信息。
select
d.deptno,d.dname,count(1) as empcount
from
emp e inner join dept d on e.deptno = d.deptno
group by d.deptno
having empcount >= 5
14.2.10 查詢出薪資高于公司薪資的平均水平的員工名稱,所在部門,上級領(lǐng)導名稱,員工名稱的薪資等級
首先這里需要所有表都參與。emp表查詢出員工和領(lǐng)導的信息,所在部門需要dept表,員工薪資水平需要salgrade表。
需要查詢員工名稱,所在部門,上級領(lǐng)導名稱,員工名稱的薪資水平
分成四步走:
1、查詢出員工信息和所在部門的信息。
2、在上述的基礎(chǔ)上篩選出薪資高于公司平均水平的員工。
3、在上述的基礎(chǔ)上再追加查詢員工的領(lǐng)導名稱。
4、在上述的基礎(chǔ)上,再追加查詢員工的薪資水平。
-- 查詢出薪資高于公司薪資的平均水平的員工名稱,所在部門,上級領(lǐng)導名稱,員工名稱的薪資水平
# 需要查詢員工名稱,所在部門,上級領(lǐng)導名稱,員工名稱的薪資水平
# 分成四步走:
# 1、查詢出員工信息和所在部門的信息。
select
e.ename,d.dname
from
emp e inner join dept d on e.deptno = d.deptno;
# 2、在上述的基礎(chǔ)上篩選出薪資高于公司平均水平的員工。
select
e.ename,d.dname
from
emp e inner join dept d on e.deptno = d.deptno
where e.sal > (select avg(sal) from emp);
# 3、在上述的基礎(chǔ)上再追加查詢員工的領(lǐng)導名稱。
select
e.ename 員工名稱,d.dname 員工部門, m.ename 領(lǐng)導名稱
from
emp e inner join dept d on e.deptno = d.deptno
left join emp m on e.mgr = m.empno
where e.sal > (select avg(sal) from emp);
# 4、在上述的基礎(chǔ)上,再追加查詢員工的薪資水平。
select
e.ename 員工名稱,d.dname 員工部門, m.ename 領(lǐng)導名稱,s.grade 員工薪資等級
from
emp e inner join dept d on e.deptno = d.deptno
left join emp m on e.mgr = m.empno
inner join salgrade s on e.sal between s.losal and s.hisal
where e.sal > (select avg(sal) from emp);
14.2.11 查詢與’SCOTT’從事相同工作的員工名稱和部門名稱
首先需要查詢emp和dept的關(guān)聯(lián)查詢,同時需要子查詢來找到’SCOTT’的工作作為條件篩選的值
需要查詢員工名稱和部門名稱
分成兩步走
1、正常的查詢出員工的名稱和所在的部門
2、基于’SCOTT’從事的工作篩選出對應(yīng)的員工信息
-- 查詢與'SCOTT'從事相同工作的員工名稱和部門名稱
# 需要查詢員工名稱和部門名稱
# 分成兩步走
# 1、正常的查詢出員工的名稱和所在的部門
select
e.ename,d.dname
from
emp e inner join dept d on e.deptno = d.deptno;
# 2、基于'SCOTT'從事的工作篩選出對應(yīng)的員工信息
select
e.ename,d.dname
from
emp e inner join dept d on e.deptno = d.deptno
where
e.job = (select job from emp where ename = 'SCOTT') and ename != 'SCOTT';
14.2.12 查詢沒有員工的部門信息(exists)
首先,查詢時其實依然是emp和dept表之間的一個聯(lián)系。需要查詢出員工表中不存在的deptno,但是dept表存在的部門信息。
exists是可以追加到條件里的。
語法:where exists (查詢)
上述語法中,如果 (查詢) 有結(jié)果,相當于條件滿足,會返回當前數(shù)據(jù),如果 (查詢) 沒有結(jié)果,相當于不滿足條件,不會返回當前結(jié)果。
在exists前,可以追加not,效果就是取反的效果了。
可以在查詢部門時,基于emp表的查詢結(jié)合exists來做到,如果查詢有員工信息,返回true,不返回當前結(jié)果,如果返回false,希望返回結(jié)果。
select
d.deptno,d.dname,d.loc
from
dept d
where
not exists (select empno from emp e where e.deptno = d.deptno);
14.2.13 查詢部門的平均薪資,以2000作為點,返回’大于2000’或者’小于2000’或者’等于2000’的結(jié)果
首先查詢平均薪資,必然會用到員工表和部門表兩個信息。
查詢部門編號,以及部門的薪資導致是大于,小于,等于2000的結(jié)果。
需要使用到case when then end這種操作。
分成兩步操作
1、查詢每個部門的平均薪資。
2、基于上述查詢,將平均薪資的返回結(jié)果替換為需求中的大于,小于,等于2000的結(jié)果。
-- 查詢部門的平均薪資,以2000作為點,返回'大于2000'或者'小于2000'或者'等于2000'的結(jié)果
# 查詢部門編號,以及部門的薪資導致是大于,小于,等于2000的結(jié)果。
# 分成兩步操作
# 1、查詢每個部門的平均薪資。
select
d.deptno,
avg(e.sal)
from
emp e inner join dept d on e.deptno = d.deptno
group by d.deptno;
# 2、基于上述查詢,將平均薪資的返回結(jié)果替換為需求中的大于,小于,等于2000的結(jié)果。
select
d.deptno,
avg(e.sal) 平均薪資,
case
when avg(e.sal) = 2000 then '等于2000'
when avg(e.sal) > 2000 then '大于2000'
else '小于2000'
end as 是否大于2000
from
emp e inner join dept d on e.deptno = d.deptno
group by d.deptno;
14.3 常見錯誤
柚子快報邀請碼778899分享:數(shù)據(jù)庫 MySQL詳解
推薦閱讀
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。