主頁 >  其他 > 四萬字的 MySQL 詳細入門學習(附帶練習題)

四萬字的 MySQL 詳細入門學習(附帶練習題)

2020-10-06 15:45:51 其他

寫在前面:本博客是根據動力節點課程所寫的筆記,原視頻鏈接:https://www.bilibili.com/video/BV1fx411X7BD?p=1
關于這篇博客,可能內容比較基礎,很多細節的東西沒講到,后面我還會繼續跟進這篇博客,做好修改,

目錄

一、資料庫簡介
二、安裝MySQL
三、DB、DBMS、SQL的關系
四、表
五、SQL陳述句的分類
六、匯入初始化資料
七、查看表結構以及表中的資料
八、MySQL的常用命令
九、查詢簡介及簡單查詢
十、條件查詢
十一、排序查詢
十二、分組查詢
十三、去重查詢
十四、連接查詢
十五、子查詢
十六、聯表查詢
十七、分頁查詢
十八、表的創建
十九、插入資料
二十、修改資料
二十一、洗掉資料
二十二、修改表結構
二十三、約束
二十四、存盤引擎
二十五、事務
二十六、索引
二十七、視圖
二十八、資料庫的匯入匯出
二十九、設計三范式
三十、作業題

一、資料庫簡介

回到目錄

在學習資料庫之前,我們回憶一下在IO流中所學習的一個序列化流和反序列化流,可以向檔案中存入物件,也可以從檔案中取出物件,這無疑是存盤和取出資料的一種形式,
我們學習資料庫,也是為了操作資料,其包括對資料的增加、洗掉、修改、和查詢,那你就會問了,既然二者功能相同,那為什么不能直接用序列化流呢?
那肯定是因為【資料庫管理系統】來操作資料更加簡單啊,只需要通過簡單的sql陳述句就能完成對資料的操作,不需要向序列化流那樣,需要創建物件啊,存入檔案啊,關閉流啊等等麻煩的操作,

什么是資料庫?
本質上是一個檔案夾,先有個概念,往下文看你就知道了,

什么是資料庫管理系統(DBMS)呢?
顧名思義,管理資料庫的軟體,常見的有MySQL(免費,供初學者學習的),Oracle(付費,性能比MySQL好很多,一般是公司中使用的),SQL Server(大學課程中都用這個DBMS來教學),


二、安裝MySQL

回到目錄

為了學習資料庫,接下來,我們安裝一個資料庫管理系統MySQL,安裝與配置,我都寫在一篇博客里了,很詳細,還有百度網盤鏈接,這里就不花篇幅寫了
https://blog.csdn.net/weixin_43724203/article/details/108651956


三、DB、DBMS、SQL的關系

回到目錄

上文提到幾個概念DB、DBMS、SQL,來總結一下,看看他們之間的關系,

DB(DataBase):本質是檔案夾,用來存盤資料
DBMS(DataBase Management System):資料庫管理系統,用來管理資料庫,也就是對資料庫中的資料進行管理
SQL(Structure Query Language):結構化查詢語言,DBMS使用SQL來管理DB,SQL是高級語言,計算機不能直接讀懂,因此SQL在執行前,內部會先編譯,這個編譯程序由DBMS完成,


四、表【table】

回到目錄

資料庫(檔案夾)是不能直接存放資料的,需要有檔案來存盤,我們稱資料庫中的檔案為表,

什么是表?看圖,在資料庫中,表和excel中設計的表基本一樣,是二維表格,【一個表對應一個檔案
也就是說,表是資料庫的基本組成單元,其資料以表格形式組織起來,可讀性很強,
在這里插入圖片描述
學習表,那么我們就要學習欄位,以及對記錄的操作方法,

首先我們來看【欄位】,

每一個欄位包括哪些屬性呢?
欄位名、欄位型別、相關約束,
欄位名就不需要解釋了,根據我們的需要進行命名即可;
欄位型別的話,從上表可以看出,對于姓名,“張三”和“李四”可以看成是字串型別;對于年齡,“15”和“17”可以看成是整型,在資料庫中,字串型別用varchar表示(java中用String),整型用 int 表示(和java一樣),
相關約束就是,給欄位加一些條件,該欄位對應的資料,必須滿足這些條件,資料才有效,否則會報錯,比如姓名的約束是 not null ,那么當姓名為空的時候,就會報錯,


五、SQL陳述句的分類

回到目錄

在我們認識了DB、DBMS、表這三個概念之后,還有一個沒講,就是SQL,作為操作資料的語言,SQL自然是很重要的知識點,這里,我們先看看它的分類,
對于其分類,先有個大概的認識,

DDL(Data Definition Language):資料庫定義語言,主要關鍵字:create drop alter,對表的結構的增刪改
DML(Data Manipulation Language):資料庫操縱語言,主要關鍵字:insert delete update,對表的資料的增刪改
DQL(Data Query Language)【最重點】:資料庫查詢語言,主要關鍵字:select,包含select的sql陳述句都是查詢陳述句,
DCL(Data?Control?Language):資料庫控制語言,主要關鍵字:grant授權、revoke撤銷權限
TCL(Transaction Control?Language):事務控制語言,主要關鍵字:commit提交事務,rollback回滾事務

這里的關鍵字,先知道就行,后面學習就會了,不過,關于五個分類,DDL、DML、DQL、DCL、TCL以及它們的作用,還是要記憶一下先,


六、匯入初始化資料

回到目錄

學習完前面一些概念之后,我們先匯入一些資料,方便我們后面的練習,

匯入初始化資料,有以下幾個步驟:
1)打開cmd視窗,登陸我們的MySQL
在這里插入圖片描述
2)創建一個資料庫,來存放我們的練習資料(陳述句看不懂沒關系,先跟著敲)

create database if not exists bjpowernode;

使用資料庫

use bjpowernode;

3)匯入我們的資料:新建一個檔案,命名為 bjpowernode.sql ,打開,將下面的代碼復制粘貼進去,然后回到我們的 cmd 視窗,輸入以下命令:source 路徑\bjpowernode.sql;(注意,這里的“路徑”中不能有中文),這樣,我們就把資料匯入bjpowernode這個資料庫中了,

【注意:下面的代碼直接復制粘貼就行,經過后面的學習,就能夠看懂了】

DROP TABLE IF EXISTS EMP;
DROP TABLE IF EXISTS DEPT;
DROP TABLE IF EXISTS SALGRADE;

CREATE TABLE DEPT
       (DEPTNO INT(2) NOT NULL ,
	DNAME VARCHAR(14) ,
	LOC VARCHAR(13),
	PRIMARY KEY (DEPTNO)
	);
CREATE TABLE EMP
       (EMPNO INT(4)  NOT NULL ,
	ENAME VARCHAR(10),
	JOB VARCHAR(9),
	MGR INT(4),
	HIREDATE DATE  DEFAULT NULL,
	SAL DOUBLE(7,2),
	COMM DOUBLE(7,2),
	PRIMARY KEY (EMPNO),
	DEPTNO INT(2) 
	)
	;

CREATE TABLE SALGRADE
      ( GRADE INT,
	LOSAL INT,
	HISAL INT );




INSERT INTO DEPT ( DEPTNO, DNAME, LOC ) VALUES ( 
1, '財務部', '北京'); 
INSERT INTO DEPT ( DEPTNO, DNAME, LOC ) VALUES ( 
2, '研發部', '上海'); 
INSERT INTO DEPT ( DEPTNO, DNAME, LOC ) VALUES ( 
3, '銷售部', '深圳'); 
INSERT INTO DEPT ( DEPTNO, DNAME, LOC ) VALUES ( 
4, '管理層', '廣州'); 
COMMIT;
 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
1000, '張三', '文員', 1003,  '1980-12-17'
, 800, NULL, 2); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
1001, '李四', '銷售員', 1005,  '1981-02-20'
, 1600, 300, 3); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
1002, '王五', '銷售員', 1005,  '1981-02-22'
, 1250, 500, 3); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
1003, '趙六', '經理', 1008,  '1981-04-02'
, 2975, NULL, 2); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
1004, '劉備', '銷售員', 1005,  '1981-09-28'
, 1250, 1400, 3); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
1005, '關羽', '經理', 1008,  '1981-05-01'
, 2850, NULL, 3); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
1006, '張飛', '經理', 1008,  '1981-06-09'
, 2450, NULL, 1); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
1007, '皮卡丘', '研發人員', 1003,  '1987-04-19'
, 3000, NULL, 2); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
1008, '小火龍', '董事長', NULL,  '1981-11-17'
, 5000, NULL, 4); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
1009, '妙蛙草', '銷售員', 1005,  '1981-09-08'
, 1500, 0, 3); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
1010, '杰尼龜', '文員', 1006,  '1987-05-23'
, 1100, NULL, 2); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
1011, '鋼鐵俠', '文員', 1005,  '1981-12-03'
, 950, NULL, 3); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
1012, '蜘蛛俠', '研發人員', 1003,  '1981-12-03'
, 3000, NULL, 2); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
1013, '永強', '文員', 1006,  '1982-01-23'
, 1300, NULL, 1); 
COMMIT;
 
INSERT INTO SALGRADE ( GRADE, LOSAL, HISAL ) VALUES ( 
1, 700, 1200); 
INSERT INTO SALGRADE ( GRADE, LOSAL, HISAL ) VALUES ( 
2, 1201, 1400); 
INSERT INTO SALGRADE ( GRADE, LOSAL, HISAL ) VALUES ( 
3, 1401, 2000); 
INSERT INTO SALGRADE ( GRADE, LOSAL, HISAL ) VALUES ( 
4, 2001, 3000); 
INSERT INTO SALGRADE ( GRADE, LOSAL, HISAL ) VALUES ( 
5, 3001, 9999); 
COMMIT;

4)輸入 show tables; 發現我們的bjpowernode這個資料庫中多了幾個表

在這里插入圖片描述

關于bjpowernode.sql這個檔案
在上面的操作中,我們已經向資料庫匯入了資料,且是通過bjpowernode.sql這個檔案進行匯入的,
那么,什么是sql腳本呢?
(以sql結尾的檔案,我稱為“sql腳本”,這種檔案中,撰寫了大量的sql陳述句,通過source命令執行sql腳本,就是將這個腳本中的sql陳述句一一執行,)


七、查看表結構以及表中的資料

回到目錄

在操作表中的資料之前,先查一下表的結構,是有必要的,

我們先看看,bjpowernode這個資料庫中,有哪些表

查看dept表的表結構
在這里插入圖片描述

這里我先介紹一下,讓大家能看懂上面的表

Field是欄位名稱,Type是欄位型別,Null、Key、Default、Extra這些是欄位約束,
欄位型別中,int(2)、varvhar(14),后面的數字,表示寬度,但是,int和varchar二者的寬度,含義還不一樣,
對于int(2),不是說你的數字大小只能是0~99,而是說,當你給欄位deptno添加UNSIGNED ZEROFILL這個約束
時,如果你的值是1,那么會自動幫你補齊為 01,
對于varchar(14),是說在你的字串中,無論是字母還是符號還是中文,都不能超過14和字符,一旦超過14個,
就會報錯,
欄位約束中,null空約束,yes時表示該欄位可以為空,no時反之;key是主鍵約束;default是默認約束,也就是
對于該欄位的默認值,這些約束在后面會細講,

這里,我們把各個表的欄位都介紹一下,順便了解一下各個欄位的含義,方便后面的理解和練習

dept表(部門表):deptno(部門編號)、dname(部門名稱)、loc(部門位置)
emp表(員工表):empno(員工編號)、ename(員工姓名)、job(作業崗位)、mgr(上級領導編號)、hiredate(入職日期)、sal(月薪)、comm(津貼)、deptno(部門編號)
salgrade表(薪資等級表):grade(等級)、losal(最低薪資)、hisal(最高薪資)

接下來,查一下我們的表都有哪些資料,命令復制粘貼就行,后面會學





八、MySQL的常用命令

回到目錄

MySQL中有一些常用的命令,但是不難,一下子就記住了

select database(); -- 查看當前正在使用的資料庫

select version(); -- 查看當前MySQL的版本

show create table emp; -- 查看emp這個表的創建陳述句

show create table emp; 這句執行之后,效果如下:


畫紅框的部分,就是我們創建emp這個表的時候,所需要的sql陳述句


九、查詢簡介及簡單查詢

回到目錄

在開始學習查詢之前,我們先了解查詢順序,你可以看不懂,但是在后面學習完它們的含義之后,這個執行順序你要記得住:
【from、join、on、where、group by、having、select、distinct、order by、limit】
【我的記憶方法】從加上哪組,有選重排限(英語直譯取第一個漢字),十個字,沒什么邏輯,但是記住之后,寫sql查詢陳述句相當簡單,你不用每一次都跑回來,看看這些執行順序,方法很蠢但有用

在前面的sql分類中,我們學到過一種,叫做DQL,這就是查詢陳述句,其語法格式很簡單,如下:【這是最簡單的查詢方式,后面會越來越難,先記住這個格式】

select 欄位名1,欄位名2,欄位名3... from 表名

大家可以嘗試一下下面的代碼,根據我的解釋和你實際看到的結果,就很容易理解

select * from emp; -- 查詢所有的員工記錄
select ename,sal from emp; -- 查詢員工姓名即對應的薪資
select ename,sal*2 from emp; -- 在第二句的基礎上,查出的結果是原薪資的兩倍
select ename 員工姓名,sal*2 薪資 from emp; -- 在第三局的基礎上,給欄位起別名

有幾個注意點,新手比較容易錯
1)sql陳述句是不區分大小寫的
2)陳述句要以 ; 結尾
3)字串是用單引號 ’ ’ 括起來的


十、條件查詢

回到目錄

什么是條件查詢?
我們在簡單查詢之后,有一些資料是我們想要的,有些是我們不想要的,那么我們就需要給查詢陳述句加一些條件進行篩選,這就是條件查詢,

條件查詢的語法格式如下:

select
	欄位...
fromwhere
	條件;

既然是條件,那么我們當然需要一些運算子,比如滿足 A=B 這個條件時,就把記錄查出來, ‘=’ 就是一個運算子,常見的運算子如下:

運算子說明
= ,!=,>,<,>=,<=等于,不等于,大于,小于,大于或等于,小于或等于
between…and…兩個值之間
is null某個欄位對應的資料為空
and并且
or或者
in包含,注意 num in (2,4) 表示的不是將 num 在 2 到 4 這個范圍內的記錄查出來,而是說 num=2 或者 num=4 時將記錄查出來
not非,常和 is 、 in 連用,即 is not null(不為空)、not in(不在)
like有 like 的查詢陳述句稱為模糊查詢

這里舉幾個例子,還是老規矩,大家執行sql陳述句,看看效果,很容易懂的

select * from emp;
select * from emp where empno = 1000; -- 這里可以看到,只查詢了 empno = 1000 時這條記錄
select * from emp where sal > 1000;
select * from emp where sal between 1000 and 2000; -- 將薪資在1000到2000范圍內的記錄查出來
select * from emp where mgr is null; -- 結果是將董事長查出來了,因為懂事長已經是最高職位,沒有上司,為null
select * from emp where empno = 1000 and empno = 1001;
select * from emp where empno in (1000,1001,1002);

重點講一下模糊查詢,模糊查詢一般是根據字串來對記錄進行篩選,其支持兩個符號,下劃線 _ 和百分號 % ,下劃線表示必須是某個字符且不能為空,% 表示任意多個字符且能為空,
sql陳述句如下:

select * from emp where job like "%售%"; -- 顯然,可以將所有銷售員查詢出來
select * from emp where job like "_售_"; -- 查詢結果和上一句一樣,因為 % 雖然能表示任意多個字符,但是 銷售員 只有三個字,% 只指代了一個字符

select * from emp where ename like '%張%'; -- 查出兩條記錄,因為 % 能表示空
select * from emp where ename like '_張%'; -- 查出0條記錄,因為 _ 必須是具體的字符,不能為空

關于上面的幾個運算子,還有一些注意點:
1)between…and…,是左閉右閉,及表示范圍的這兩個數也是包括在內的
2)null 不是一個值,要用 is null 或者 is not null 判斷,不能使用等號,比如 where mrg = null 來查詢董事長,是錯誤的,
3)and 的優先級大于 or,所以當 and 和 or 同時出現時,最好加上括號區分優先級
4)模糊查詢中_ 和 % 既然有特定的含義,那如果我確實需要 _ 這個符號來查詢呢?答案是在 _ 前面加一個 \,這一點和 java 中是一樣的,


十一、排序查詢

回到目錄

我們都知道,在我們每一次考完試之后,老師都會根據分數對班里的人進行排序,因為不排序的話,對于雜亂無章的成績,很難看出誰是第一,誰是第二等等,
在 mysql 中,我們也可以將查詢到的結果進行排序,讓查詢結果更加清晰,
執行以下 sql 陳述句:

select ename,sal from emp order by sal asc; -- 根據薪資降序查詢
select ename,sal from emp order by sal desc; -- 根據薪資升序查詢

回到生活中,當老師發現小明和小紅的語文成績都是90,語數英三科總分也相等,那么怎么排序呢,老師一般會再次比較數學的成績,進行排序,

select ename,sal from emp order by sal asc,comm asc; -- 如果兩個人的薪資相等,那么久根據津貼comm進行排序

【練習題】找出所有銷售員,并根據薪資降序排序

select * from emp where job = '銷售員' order by sal desc;

十二、分組查詢

回到目錄

在一個班級里,我們不是所有人都擠在一起,老師一般都會為我們分組,考試后通過比較各組的平均分,來判斷哪一組成績比較差,才能更有針對性地對該組進行輔導,

同樣的,我們對于一個表,我們可以用 group by 將表分成多個組,然后比較各個組的平均值等,比如,在 emp 員工表中,我們可以根據不同的崗位,對員工進行分組,然后根據薪資的平均值,了解各個崗位的薪資情況,

在了解分組查詢之前,我們先了解一下分組函式
分組函式:sum()、max()、min()、avg()、count(),分組函式又稱為多行處理函式,這是因為它是對多行資料進行操作,還有一種單行處理函式,都會進行介紹,

select sum(sal) from emp; -- 查出薪資的總值
select max(sal) from emp; -- 查出薪資的最大值
select min(sal) from emp; -- 查出薪資的最小值
select avg(sal) from emp; -- 查出薪資的平均值

select count(*) from emp; -- 查出總記錄數(14條)
SELECT COUNT(sal) FROM emp; -- 查出14條記錄
SELECT COUNT(comm) FROM emp; -- 查出4條記錄

對上述sql的總結:
1)對于上述五種分組函式,我們發現,查詢結果都是單行,這是因為,我們還沒有對表 emp 進行分組,下面學習完分組,就有多行了,
2)對于 count() 這個分組函式,count() 是用來統計記錄條數的,* 表示所有的記錄條數,如果是欄位,則統計其非空的情況下的記錄條數,如 count(sal) 查出了14條記錄,但 count(comm) 查出的只有4條,這是因為,comm這個欄位只有4條記錄中有資料,其他的都為null,


學習完多行處理函式之后,我們再來看一下單行處理函式,較為常用的是:
我們來執行以下的sql:

-- 假設我們要查出員工表中,員工名以及他們的年薪((每月薪資+每月津貼)*12)
select ename,(sal+comm)*12 年薪 from emp; -- 查出來發現,年薪有的人變成了null,

這是因為,在單行中,有員工是沒有津貼的,及津貼是null,所以 sal+null 的結果還是null,【我們可以用單行處理函式 ifnull() 來解決,】sql陳述句如下:

select ename,(sal+ifnull(comm,0))*12 年薪 from emp;

單行處理函式 ifnull() 的格式是,ifnull(欄位,數值),ifnull(comm,0) 對應的意思就是,如果津貼是 null 的話,就把它轉換成數字 0 來和 sal 做相加運算,


好了,接下來學習一下分組排序吧,
【由于分組函式經常與group by(分組)連用,因此被稱為分組函式】

select job,avg(sal) from emp group by job; -- 根據職業進行分組,并查出各個職業的平均薪資,

就是這么簡單,經過上面的sql陳述句,我們將表通過崗位進行了分組,并且通過分組函式求出了各個崗位對應的平均薪資,
此時,在查出各個崗位的平均薪資的時候,如果我們再加一個條件,需要查出平均薪資大于2999的崗位,顯然,大于2999,需要進行條件查詢,那么我們試一下下面的sql陳述句

select job,avg(sal) from emp group by job where avg(sal) > 2999; 

發現報錯了!這是什么原因呢?回顧我們在開始學查詢時,我讓大家記住一個查詢順序,【from、join、on、where、group by、having、select、distinct、order、limit】,顯然,group by 是在where后面的,而分組函式 avg(sal) 又是在group by 后面執行的,也就是說,由于where是在分組函式之前執行,因此 where avg(sal) > 2999 是錯誤的,說白了,就是你 avg(sal) 都還不存在,那怎么執行where,就是這個道理,
小總結:這里很重要,分組函式不能寫在 where 后面,這是錯誤的!
為此,我們引入了【另一個關鍵字 having ,其作用和 where 相同】,都是條件查詢,不同點就是 where 在 group by 之前執行,而 having 在 group by 之后執行,也就是分組之后,通過 having 對資料進行再次過濾,

-- 查出平均薪資大于2999的崗位
select job,avg(sal) from emp group by job having avg(sal) > 2999;

【練習題】找出薪資高于平均薪資的所有員工

select ename,sal from emp where sal > avg(sal);

前面已經說到,由于各關鍵字的查詢順序,where 和 avg() 這些分組函式不能連用,那該怎么解決這道練習題呢?我們用到【子查詢】,
【這里先做個伏筆,子查詢后面會學習,這道題只是再次提醒你,where 和 分組函式不能連用】

-- 分兩步查詢
select avg(sal) from emp; -- 查出所有員工的平均薪資
select ename,sal from emp where sal > 2073.214286; -- 根據上條sql的查詢結果,找出薪資高于平均薪資的員工

-- 一步查詢
select ename,sal from emp where sal > (select avg(sal) from emp); -- 這個就是子查詢,后面會學,

關于分組查詢另外三個知識點
1) 多欄位問題
我們來看看這個sql陳述句

select ename,job,avg(sal) from emp group by job;

這個sql陳述句執行錯誤,你想想,我們要的是根據崗位進行分組,并顯示崗位對應的平均工資,和單個員工ename有啥關系,你寫個ename在這里,mysql究竟該顯示誰?顯然是不合理的,
有個規定:【當一條陳述句中有group by的話,select后面只能跟分組函式和參與分組的欄位】

2) 多次分組
在前面的學習中,我們知道 order by 可以在后面加兩個欄位,在第一個欄位相等時,再根據第二個欄位進行排序,
類似的,如果我們要求:找出每個部門不同作業崗位的最高薪資,顯然,我們需要線根據部門分組一次,再根據崗位再分組一次,

select deptno,job,max(sal) from emp group by deptno,job;

3) having和where的選擇
首先,在某些情況下,having 和 where 都是可以使用的,
【練習題】找出最高薪資大于2900的部門

select deptno,max(sal) from emp group by deptno having max(sal) > 2900;

select deptno,max(sal) from emp where sal > 2900 group by deptno;

以上兩種方式查出來的結果是一樣的,但是having的效率比where低,原因:第二個sql陳述句中,先將薪資小于2900的員工過濾掉,這樣參與分組的員工就少了,效率就高了,


十三、去重查詢

回到目錄

我們先執行一下下面的sql陳述句

select deptno from emp;

我們發現,資料冗余的太多了,很多都是重復的,那么我們該怎么去掉這些重復的內容呢?很簡單

select distinct deptno from emp;

如上,只需要在欄位前面加上 distinct 即可,
我們這種情況只有一個欄位,那么多個欄位時,會是怎樣呢?

select distinct deptno,job from emp;

和我們想的不一樣,它并不是只對 deptno 這個欄位起效果,而是對 deptno、job 這兩個欄位同時起效果,它要求 deptno 和 job 兩個欄位對應的值不能夠同時重復,

【練習題】統計崗位的數量

select count(distinct job) from emp;

十四、連接查詢【重點】

回到目錄

關于連接查詢,我已經寫過一篇很詳細的博客了,快車直達:https://blog.csdn.net/weixin_43724203/article/details/108678299

【練習題】找出每一個員工的部門名稱以及工資等級

select
	e.ename,d.dname,s.grade
from
	emp e
join
	dept d
on
	e.deptno = d.deptno
join 
	salgrade s
on
	e.sal between s.losal and s.hisal;

【練習題】找出每一個員工的部門名稱、工資等級、以及上級領導

SELECT
	e1.ename '員工',d.dname,s.grade,e2.ename '領導'
FROM 
	emp e1
LEFT JOIN
	emp e2
ON
	e1.mgr = e2.empno
JOIN
	dept d
ON
	e1.deptno = d.deptno
JOIN
	salgrade s
ON
	e1.sal BETWEEN s.losal AND s.hisal;

十五、子查詢

回到目錄

首先我們要知道,什么是子查詢?
select陳述句A中,可以嵌套另一個select陳述句B,則select陳述句B稱為子查詢,

子查詢可以出現在什么地方?

select
	...(select)
from
	...(select)
where
	...(select);

舉例
在where中使用子查詢:找出高于平均薪資的員工資訊

select * from emp where sal > (select avg(sal) from emp);

在from后面嵌套子查詢:找出每個部門平均薪資的薪資等級

SELECT deptno,AVG(sal) FROM emp GROUP BY deptno; -- 先查出每個部門的平均薪資,將結果作為一個表,和salgrade表連接

select
	t.*,s.grade
from
	(SELECT deptno,AVG(sal) as avgsal FROM emp GROUP BY deptno) t
join
	salgrade s
on
	t.avgsal between s.losal and s,hisal;

在select后面嵌套子查詢:找出每個員工所在的部門名稱,要求顯示員工名和部門名

select 
	e.ename,(select d.dname from dept d where e.deptno = d.deptno) as dname 
from 
	emp e;

十六、聯表查詢

回到目錄

所謂聯表查詢,就是使用 union 關鍵字,將查詢結果集相加,這個程序中,會自動將重復的記錄洗掉,
比如,我們要找出作業崗位是 銷售員 和 經理 的員工,

-- 方式一
select ename,job from emp where job in ('銷售員','經理');

--方式二
select ename,job from emp where job = '銷售員'
union
select ename,job from emp where job = '經理';

【注意】:
聯表查詢和連接查詢都是多表查詢,聯表查詢是縱向查詢,連接查詢是橫向查詢,如何理解呢?
縱向查詢,先查出崗位為銷售員的所有員作業為表 A ,再查出崗位為經理的所有員作業為表 B ,union 是將 B 從 A 的下方拼湊上去,合成更多條記錄,因此稱為縱向查詢,
橫向查詢,從上面的學習中我們知道,當我們所需要的欄位在不同的表上時,我們就要連接多個表,然后將各個欄位拼湊起來,當然,是左右關系的拼湊,因此稱為橫向查詢,


十七、分頁查詢

回到目錄

limit 分頁查詢(是非常重要的知識點,不難,但是很重要!)

在實際查詢中,我們查詢到的資料可能會很多很多,我們不可能一次性全部查出來,顯示在我們的瀏覽器上,比如,我們百度一下某個問題,假設沒有分頁的話,那我們要下拉時,不知道要拉多久才能到底,
在這里插入圖片描述

limit 語法格式:limit startIndex,length,
startIndex是起始位置,從0開始,0是第一條記錄,
length表示查多少條記錄作為一頁,
再次回到我們的查詢順序,可以看到,limit是最后處理的一個關鍵字,
sql陳述句如下:

select * from emp limit 0,5;
select * from emp limit 5,5;

現在,我們來總結一下一個規律:
第一頁:0,3
第二頁:3,3
第三頁:6,3
第四頁:9,3
后面的 3 是不變的,不信你百度一下后,去數一數一頁有多少條記錄,都是固定的,前面的記錄下標就一直變化,規律是:【(頁碼-1)x 每頁條數 】

寫成java代碼

int pageNo = 1; //頁碼
int pageSize = 10; //每頁多少條記錄

limit (pageNo-1)*pageSize,pageSize

十八、表的創建

回到目錄

在前面的學習中,我們一直使用的資料,是通過 sql 腳本匯入的,我們發現,我們都會查詢陳述句了,但是我們自己還不會創建表,現在,就來學習學習吧,

創建表的格式如下:

 create table 表名{
        欄位1 資料型別 約束,
        欄位2 資料型別 約束,
        ....
};

先看看資料型別吧:資料型別有整型、浮點型、日期型、字串型,常見的有如下
整型

型別位元組最小值最大值
tinyint1-128127
-128127
smallint2-3276832767
065535
mediumint3-83886088388607
016777215
int4-21474836482147483647
04294967295
bigint8-922337203685477580892233720368547758087
018446744073709551615

浮點型

型別位元組最小值最大值
float41.4x10^(-45)3.4x10^38
double84.9x10^(-324)1.7x10^308

日期型

型別說明標準格式位元組
date日期YYYY-MM-DD3
time時間HH:MM:SS3
datetime日期時間YYYY-MM-DD HH:MM:SS8
timestamp時間戳,從1970年1月1日0時起到現在的毫秒數4
year年份YYYY1

字串型

型別說明范圍
char定長度字串char(M),0<=M<=255,也就是最多255個字符,對于char(3),如果你存盤 ‘abcde’,就會報錯,
varchar變長度字串varchar(M),0<=M<=65535(約2W-6W個字符,受字符集影響)
text文本串約2W-6W個字符,受字符集影響

【思考】char和varchar怎么選擇?
char分配的長度是固定長度,會直接分配空間,不需要和varchar一樣先判斷字串長度,因此char的效率比varchar高,在實際的開發中,一些不需要很多字符、且長度固定的欄位,就選用char,比如性別等;一些長度不固定的欄位,就選用varchar,比如簡介等,


現在,我們開始建表吧,
注意:表名以 t_ 或者 tbl_ 開頭,你就會問了,我們除了創建表,還能創建其他的嗎?為什么要加 t_ 或 tbl_ 來區分?有的,后面還會學索引、視圖,

【練習題】創建一個 t_student表,要求如下

學生資訊包括:學號、姓名、性別、班級編號、生日
學號:bigint
姓名:varchar
性別:char
班級編號:int
生日:char
create table t_student(
	no bigint,
	name varchar(255),
	sex char(1),
	classno int,
	birth char(10)
);

執行以上sql,我們的 t_student 表就創建好了
創建表之后,我們如果要洗掉表,可執行以下sql

drop table if exists t_student;

【表的復制】:表的復制,是將一個查詢結果,作為一張新表,sql陳述句如下

create table emp1 as select ename from emp; -- 將emp的查詢結果作為新表emp1

select * from emp1; -- 檢查我們的emp1表是否創建成功

show create table emp1; -- 查看emp1的創建程序,發現和手動創建的沒啥區別

十九、插入資料

回到目錄

在前面的學習中,我們發現,從九到十七,都是在將查詢陳述句,可見查詢的重要性,
現在,我們來學插入陳述句,

插入陳述句非常簡單,語法格式如下:
insert into 表名(欄位1,欄位2…) values(值1,值2…);
插入陳述句有兩種形式,一種是分開插入,一種是一次性插入多個記錄,

-- 方式一
insert into t_student(no,name,sex,classno,birth) values(1,'張三','男',1000,'7月1日');
insert into t_student(no,name,sex,classno,birth) values(2,'李四','男',1001,'7月20日');

-- 方式二
insert into t_student(no,name,sex,classno,birth) values(1,'張三','男',1000,'7月1日'),(2,'李四','男',1001,'7月20日');

【注意】:
1)前面的欄位必須和后面的值匹配得上,
如果有的欄位沒寫出來,則會自動視為null,如下

insert into t_student(name) values('王五');

2)前面的欄位可以不寫,但這就要求后面的值要寫全

insert into t_student values(4,'趙六','男',1003,'9月9日');

【插入批量記錄】:和表的復制類似,其實我們也可以將一個查詢結果,插入到表中,sql陳述句如下:

create table emp2 as select ename from emp where ename = '張三';
select * from emp2;
insert into emp2 select ename from emp where ename != '張三';
select * from emp2;
-- 當然,這要求查詢結果和原來表的列數是一樣的

二十、修改資料

回到目錄

學習完插入資料后,我們再來學修改資料,修改資料也很簡單,

語法格式:update 表名 set 欄位名1=值1,欄位名2=值2… where 條件;
注意:如果沒有條件的話,整張表的對應欄位都會更新

【練習題】將部門 1 的所在地址修改成蘭州,將部門名稱修改為人事部

UPDATE dept SET loc='蘭州',dname='人事部' WHERE deptno = 1; 

二十一、洗掉資料

回到目錄

洗掉資料也一樣,很簡單

語法格式:delete from 表名 where 條件;

delete from dept where deptno = 1; -- 洗掉編號為1的部門

如何洗掉所有記錄?

delete from emp1; -- 洗掉所有記錄
truncate table emp1; -- 洗掉所有記錄,只剩下表頭
drop table if exists emp1; -- 整張表洗掉

兩種洗掉所有記錄有什么不同?
delete效率很低,洗掉所有記錄,沒有釋放其物理地址,其物理地址還在,也就是只是在地址上將內容抹去,我們可以想象成,在一個用鉛筆在紙上填寫的表格中,用橡皮檫把內容擦去,這樣做的好處,是資料在洗掉之后,后悔了,還能再回來,
truncate效率高,表被截斷,不可回滾,永久丟失,可以想象成紙上的表格,用剪刀將表頭以外的其他行都剪掉,我們就不能重新用鉛筆寫了,


二十二、修改表結構

回到目錄

修改表結構的sql陳述句其實有很多種,比如洗掉欄位,修改欄位名,新增欄位等等,但是,我們不學!原因如下:
1)因為我們可以在 sqlyog、navicat等MySQL的可視化工具中進行修改,
2)表一旦創建,就很少會出現修改表結構的情況(除非在前期設計表的時候),你想想看,假如一張表中已經有了幾千萬條記錄,此時你修改某個欄位,那這些記錄對應該欄位的值該怎么辦,難道要全部修改嗎?
3)在java代碼中,不會出現修改表結構的陳述句,出現在java代碼中的,一般只有【CRUD】(Create增、Retrieve檢索、Update修改、Delete洗掉,也就是我們在前面學的DML和DQL)操作,


二十三、約束

回到目錄

在前面剛剛接觸欄位的時候,我們就介紹了欄位的三個要素,欄位名,欄位型別,欄位約束,那么,什么是約束呢?
在創建表的時候,可以給表的欄位添加一些約束,添加約束的目的是為了保證資料的合法性、有效性等,

【常見約束】:

約束說明
not null非空約束,添加 not null 約束的欄位,其值不能是 null
unique唯一約束,添加 unique 約束的欄位,每條記錄對應該欄位的值不能重復
primary key主鍵約束,是非空約束和唯一約束的結合,其值不能為 null 且不能重復,簡稱為 PK
foreign key外鍵約束,和主鍵約束一樣,其值不能為 null 且不能重復,但是其還有另一種用處,后面會學,簡稱為FK
default默認值約束,可以設定欄位的默認值,如果在insert插入記錄時,其沒有設值,則使用默認值

現在,我們來單獨講講各個約束,

非空約束

create table t_temp(
	name varchar(255) not null,
	age int(11)
);
insert into t_temp(age) values(17); -- 報錯,因為name不能為 null ,而這個新增陳述句沒有給name賦值 
drop table if exists t_temp;

唯一約束:注意,null 可以不唯一

create table t_temp(
	name varchar(255) unique
);
insert into t_temp(name) values('張三'); -- 順利插入資料
insert into t_temp(name) values('張三'); -- 報錯,因為'張三'已經存在了,不滿足唯一性
drop table if exists t_temp;

-- 注意,如果是兩個寫在一起,則是聯合之后具有唯一性,如下
create table t_temp(
	name varchar(255),
	age int(11),
	unique(name,age)
); 
insert into t_temp(name,age) values('張三',15);
insert into t_temp(name,age) values('張三',16); -- 不會報錯
insert into t_temp(name,age) values('張三',15); -- 報錯
drop table if exists t_temp;

主鍵約束【重要】:
1)添加了主鍵約束的欄位稱為主鍵欄位,主鍵欄位其對應的主鍵值是這行記錄在整張表中的唯一標識,符合表的【設計三范式】(后面講),
2)主鍵約束和唯一約束一樣,也可采用復合形式,也就是多個欄位聯合起來作為主鍵,但是我們一般不這樣做,因為這樣做違背了【設計三范式】,
3)一張表中,只能有一個欄位作為主鍵,且只能有一個主鍵,
先看看sql陳述句吧

create table t_temp(
	id int,
	name varchar(255),
	primary key(id)
); 
insert into t_temp(name) values('張三'); -- 報錯,因為 int 是主鍵,不能沒有值,不能為 null 
insert into t_temp(id,name) values(1,'張三'); -- 不會報錯
insert into t_temp(id,name) values(1,'李四'); -- 報錯,因為主鍵具有唯一性
drop table if exists t_temp;

主鍵值的自增:我們的主鍵,為了滿足其非空和唯一兩個條件,我們一般會將其設定為自增,

create table t_temp(
	id int primary key auto_increment, -- 從1開始,以1遞增
	name varchar(255),
); 
insert into t_temp(name) values('張三');
insert into t_temp(name) values('李四');
select * from t_temp; -- 發現 id 已經自動幫我們寫好了
drop table if exists t_temp;

【注意】:我們一般不會使用業務主鍵,而是采用自然主鍵,什么意思呢?
我們的主鍵,必須要能代表一條記錄,且不能修改,且不能和其他的欄位有任何的關系,不要和業務掛鉤,假如我們用銀行卡號作為主鍵,當我們更換銀行卡時,我們讓銀行幫我們改卡號,完了,銀行說不能改,在底層銀行卡號是主鍵,主鍵不能修改,改了就可能和別人重復了,
所以我們采用自然主鍵,我們可以自定義一個欄位 id int,然后設 id 為主鍵,即主鍵最好是和業務無關的自然數,


外鍵約束
在學習外鍵約束之前,讓我們先來看一下下面的sql陳述句和圖片:
【下面的代碼直接復制就行了】

CREATE TABLE t_student(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(255) NOT NULL,
	classno INT NOT NULL,
	classname VARCHAR(255) NOT NULL
);
INSERT INTO t_student(NAME,classno,classname) VALUES
('張三',100,'陽光小學北京路校區四年級(1)班'),
('李四',100,'陽光小學北京路校區四年級(1)班'),
('王五',100,'陽光小學北京路校區四年級(1)班'),
('趙六',101,'陽光小學北京路校區四年級(2)班'),
('孫七',101,'陽光小學北京路校區四年級(2)班');

SELECT * FROM t_student;
drop table if exists t_student;

在這里插入圖片描述
我們發現,在classname這個欄位中,重復的資料太多了,也許你不會覺得多,這是因為這里只有幾個人,假設1班和2班,每一個同學的資訊就是一條記錄,那重復的,冗余的就多了吧?如何解決呢?我們需要用到外鍵約束,
我們將t_student這個表,分成兩個表,再用外鍵將兩個表聯系起來,就不會出現冗余了,
【下面的代碼直接復制就行了】

CREATE TABLE t_class(
	cno INT,
	cname VARCHAR(255),
	PRIMARY KEY(cno)
);
CREATE TABLE t_student(
	sno INT,
	sname VARCHAR(255),
	classno INT,
	FOREIGN KEY(classno) REFERENCES t_class(cno) -- classno稱為外鍵,關聯了t_class這個表的cno欄位
);
INSERT INTO t_class(cno,cname) VALUES
(100,'陽光小學北京路校區四年級(1)班'),(101,'陽光小學北京路校區四年級(2)班');
INSERT INTO t_student(sno,sname,classno) VALUES
(1,'張三',100),(2,'李四',100),(3,'王五',100),(4,'趙六',101),(5,'孫七',101);

SELECT * FROM t_class;
SELECT * FROM t_student;

INSERT INTO t_student(sno,sname,classno) VALUES(6,'周八',103); -- 報錯,因為classno是外鍵,其值不能是t_class的cno欄位的值中所沒有的

【注意】:
1)外鍵的值,可以是 null
2)外鍵所關聯的表的欄位,其不一定需要時主鍵,但是要求其必須是唯一性,你想想,假設其不具有唯一性,那外鍵關聯過去后,它就懵逼了,它不知道關聯哪個,
關于外鍵約束,先學到這里就好了,后面還會學,


在上面的sql陳述句中,在創建表時,我們發現,唯一約束和主鍵約束,有兩種寫法,一種是直接接在欄位后面,一種是在所有欄位都寫完之后,再寫約束,第一種其實稱為 列級約束,第二種稱為 表級約束,


二十四、存盤引擎(了解)

回到目錄

關于存盤引擎,這部分知識只是作為一個了解,如果想要深入了解的話,可以看看其他博主的博客,不過我感覺,如果不是想成為DBA的話,其實也沒有必要去深入了解,

首先,我們要知道,什么是存盤引擎?
就是表的存盤方式,比如一樣東西,我們把它放到箱子里,我們可以橫著放,也可以豎著放,這就是存盤方式的不同,【注意存盤引擎是MySQL特有的,Oracle中也有類似的機制,但它只是叫做存盤方式,沒有和MySQL一樣,整一些花里胡哨的名字,】


什么時候使用存盤引擎?
其實是在建表的時候指定的,來看看我們之前對于dept表的建表sql陳述句

CREATE TABLE DEPT(
	DEPTNO INT(2) NOT NULL ,
	DNAME VARCHAR(14) ,
	LOC VARCHAR(13),
	PRIMARY KEY (DEPTNO)
);

其實我們這樣寫是,是不完整的,我們使用查詢建表陳述句來看一下,鍵入 show create table dept;

CREATE TABLE `dept` (
  `DEPTNO` INT(2) NOT NULL,
  `DNAME` VARCHAR(14) DEFAULT NULL,
  `LOC` VARCHAR(13) DEFAULT NULL,
  PRIMARY KEY (`DEPTNO`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

且不考慮欄位的約束問題,我們來對比一下,兩個建表陳述句有什么不同:
1)首先是發現了 dept、deptno、dname 等識別符號,都加了飄號 ` ` ,可能在一些教程中,會要求我們給識別符號加上飄號,以和其他的關鍵字等進行區分,其實不加才更好, 因為這是MySQL特有的,放到Oracle中就崩了,假如你寫了上萬條sql陳述句,然后突然要求你使用Oracle這個DBMS,想想你要修改多久呀,
2)發現了后面一句 engine=innodb default charset=utf8; engine就是引擎的意思,charset是字符集的意思,我們建表的時候,沒有進行制定;但是在查建表陳述句的時候,卻給我們指定了innodb和utf8,說明innodb是默認的存盤引擎,utf8是默認的字符集,


MySQL中,存盤引擎有很多種,每一種都有自己的優缺點,需要根據需求進行選擇,
我們可以通過 SHOW ENGINES; 這個陳述句查詢MySQL所支持的存盤引擎,以下內容可以不看了,知道存盤引擎這個東西就行了,


【常見的存盤引擎:】(InnoDB和MyISAM這里就不寫了,因為視頻講的真的垃圾,了解一個引擎,又牽扯出了一大堆新的概念,最好是有高質量的博客幫助我們理解,所以你想深入了解存盤引擎,就去看其他的博客吧

MyISAM
從上面的圖,Teacnsaction – NO 我們可以知道這個存盤引擎不支持事務(事務在下一部分學習),
【糾錯】:在前面的學習中,我曾說表就是檔案,一張表就對應一個檔案,那是為了讓大家更容易理解,其實一張表,是可以對應多個檔案的,
當我們使用 MyISAM 存盤引擎創建表的時候,會生成3個檔案來對應該表,如下圖,
.frm(format)是格式檔案,存盤的是該表的表結構(欄位名、欄位型別、欄位約束這些)
.MYD(MyISAM data)是資料檔案,存盤表的資料(記錄),
MYI(MyISAM Index)是索引檔案,存盤表的索引(索引相當于書本的目錄,有了目錄,我們可以很快找到我們想要看的內容,后面會學習,),
在這里插入圖片描述



二十五、事務【重要】

回到目錄

【事務是重中之重】

一、事務簡介

1)什么是事務?
一個事務,就是一個完整的業務邏輯單元,不可再分,
說人話!比如我要在銀行進行轉賬,那我要經過哪些步驟呢?我把錢轉過去了,那我這邊的錢就變少了,到賬的用戶那邊的前就變多了,是不是就需要兩條update修改陳述句,
假如我不使用事務,我把錢轉過去,我這邊錢變少了,就在這變少的瞬間,系統崩了,那完了,到賬的那邊的錢還沒有增多,那我豈不是虧了很多錢?所以,我們需要使用事務,事務會將我們的多個sql陳述句系結成為一個整體,只有確定了所有的sql陳述句都是正確的之后,才會提交給DBMS,讓它修改資料,如果一個sql陳述句出現了差錯,那么這個事務不會被提交,所有的資料都不會發生變化,

2)事務有什么用?
從(1)問中我們就能夠知道,事務是為了保證資料的完整性和安全性,

3)與事務相關的陳述句有哪些?
只有DML陳述句,即insert、delete、update這些會讓資料發生變化的陳述句,

4)關于事務這里,我們要知道以下幾個單詞:
transaction:事務,commit:提交,rollback:回滾


舉個例子:假設一件事,需要經過insert、update、delete,然后才能完成,此時我們需要使用事務,

開啟事務,(開始)

執行insert,(不會修改資料庫的資料,會被記錄到快取中)
執行update,(不會修改資料庫的資料,會被記錄到快取中)
執行delete,(不會修改資料庫的資料,會被記錄到快取中)

提交事務或者回滾事務,(結束)  無論是提交事務還是回滾事務,都是事務結束的標志,


提交事務:根據快取中的記錄,最終修改資料庫的資料,然后清空快取中的記錄,
回滾事務:不會修改資料庫的資料,直接清空快取中的記錄,

這是用中文表述的大概意思,接下來,我們來演示事務,用sql陳述句來演示,更加直觀,


二、演示事務

先創建好表

USE bjpowernode;
CREATE TABLE t_user(
	id INT PRIMARY KEY AUTO_INCREMENT,
	username VARCHAR(255)
);
insert into t_user(username) value('zhangsan'); 

在之前的學習中,當我們執行insert、delete、update這三種DML陳述句的時候,每執行一句,我們的表中資料就會改變一次,這是因為,MySQL它是默認自動提交事務的,也就是執行一句,就會直接修改資料庫的資料,

現在,我們來模擬一下事務的回滾,看下面的sql

start transaction;  -- 這里開始,往下的所有sql,如果沒有出現回滾或者提交,都是事務的一部分

insert into t_user(username) value('lisi'); -- 插入一條記錄
update t_user set username = 'wangwu' where username = 'zhangsan';
select * from t_user; -- 查詢,發現lisi已經存在,且zhangsan被修改,我們看到的資料,現在只是存在快取
-- 中(或者說記憶體,我們關閉MySQL后重新打開,是查不到這個資料的),事實上還沒有持久化(也就是存到硬碟中),
rollback; -- 回滾
select * from t_user; -- 繼續查詢,記錄不見了,說明因為回滾,將記憶體中的執行記錄清空了,

然后我們模擬一下事務的提交,看下面的sql

start transaction;  
insert into t_user(username) value('lisi'); 
update t_user set username = 'wangwu' where username = 'zhangsan';
select * from t_user; 
commit; -- 回滾
select * from t_user; -- 繼續查詢,lisi存在,且zhangsan,說明資料已經存到硬碟中,即已經持久化,

總結:所以我們要使用事務,就是先start transaction,然后寫各種DML,最后commit或者rollback,


三、事務的四大特性 ACID

在對事務有一定的了解之后,我們來學習一下事務有哪些特性,
這四個,有時候會面試,

A:原子性:事務是最小的作業單元,不可再分,
C:一致性:事務必須保證多條DML陳述句同時成功或者同時失敗
I:隔離性:事務A和事務B之間有隔離,不能互相干擾
D:持久性:事務的最終資料必須持久化(存盤到硬碟)


四、事務的隔離性

事務的隔離性這個特性中,有一個概念,叫做隔離級別,我們會根據事務對安全性的要求,來選擇不同的隔離級別,就好像我們根據不同程度的臺風,政府部門會采取不同的應急措施一樣,
有的隔離級別中,存在一些不利于資料安全的現象,級別越低,現象越糟糕;但是,隔離級別越高,效率就會越低,所以對于隔離級別的選擇,只能到實際開發中去決定,【這個不要求初級java程式員會選擇】

隔離級別包含以下四種:讀未提交(第一級別),讀已提交(第二級別),可重復度(第三級別),序列化讀(第四級別),每一種隔離級別都是為了解決上一級隔離級別中存在的不好現象,【注意:這四種隔離級別中的“讀”字,意思都是指查詢,】
在MySQL中,是第三級別起步;在Oracle中,是第二級別起步,也就是現在的DBMS中,基本上已經沒有第一級別起步的了,接下來,我們來詳細介紹一下這四個隔離級別,然后通過演示,來加深理解和印象,

讀未提交(read uncommited):這個隔離級別中,存在“臟讀”現象,“臟讀”就是事務A還沒有執行完,還沒有提交,其要訪問或修改的資料就被事務B給讀到了,事務B讀到了“臟”的資料,所以稱為“臟讀”,
讀已提交(read commited):這個隔離級別中,解決了“臟讀”現象,存在“不可重復讀”現象,“不可重復讀”就是假設事務A還沒提交,事務B讀取資料 1 ,然后事務A提交,事務A的提交導致了資料 1 變成了 2,還沒完成提交的事務B再次讀取資料,發現兩次讀到的資料不一樣,第一次是 1,第二次是 2,也就是前后兩個資料不重復,所以稱為“不可重復讀”,
可重復讀(repeatable read):這個隔離級別中,解決了“不可重復讀”現象,存在“幻讀”現象,“幻讀”就是事務A還沒提交,事務B讀取初始資料 1,事務A提交后,修改了資料 1 使之變成了資料 2,此時事務B仍未提交,再次讀取資料,得到的結果是仍然是 1,硬碟中資料實際上已經被事務A修改成了 2,但是事務B讀到的仍然是 1,就像讀到了虛幻的資料一樣,所以稱為“幻讀”,
序列化讀(serializable):這個隔離級別中,解決了“幻讀”現象,存在效率低的現象,序列化讀就是讓事務A和事務B排隊執行,事務A沒有執行完,你事務B就不要執行,這就解決了前三個隔離級別的問題,但是由于事務排隊執行,因此效率極其低下,

以上就是四種隔離級別的介紹,怎樣,已經說的很通俗易懂了吧,現在,我們來演示一下各個隔離級別,
我們需要先打開兩個DOS命令視窗,開啟MySQL,使用bjpowernode資料庫,修改隔離級別,然后查看隔離級別確認一下,接著就可以開始我們的演示了,

修改隔離級別:set global transaction isolation level 隔離級別;
查詢隔離級別:select @@tx_isolation;   不同MySQL版本,有的是:select @@transaction_isolation;

具體如下圖:


讀未提交:


讀已提交:


可重復讀:


序列化讀:



二十六、索引(了解)

回到目錄

在學習索引之前,我們通過幾個問題,自問自答,來了解索引

1)什么是索引?
通俗地講,索引相當于書本的目錄,有了目錄我門就能很快定位到我們想要看的內容,如果沒有目錄,我們就只能從頭開始一頁一頁地翻書,知道找到我們想要的內容,

2)索引有什么用?
超大地提高了檢索記錄(emmmm,檢索的意思自行百度)的效率,

3)為什么有了索引檢索效率就會高?
因為索引縮小了掃描的范圍,我們想要查詢某條記錄,有兩種方式:1)全表掃描;2)根據索引在小范圍內掃描,

4)索引可以亂用嗎?
不可以,雖然加了索引之后檢索效率提高了,但是索引需要維護,成本高,就比如,《新華字典》改版之后,其中的漢字頁碼就會變,那前面目錄也要發生變化,同樣的,表中資料一旦修改,索引需要重新排序,進行維護,

5)什么時候需要給欄位添加索引?
資料量大(一本書假如只有10頁,那還要什么目錄);
該欄位很少有DML操作(也就是該欄位對應的資料不會經常發生改變),
該欄位經常出現在where后面,(where后面是條件,經常出現在where后面說明是經常需要根據該欄位對應的值,來查詢到該值所在的記錄),看下面

添加索引是給某一個欄位,或者說某些欄位添加索引
select * from t_user where username = '張三';
當username欄位上沒有添加索引的時候,以上sql陳述句會進行全表掃描,掃描username欄位中所有的值,
當username欄位上添加索引的時候,以上sql陳述句會根據索引進行掃描,快速定位

【注意】:主鍵和unique約束自帶索引

6)了解了索引之后,我們該怎么為我們的欄位創建索引呢?

創建索引:create index 索引名 on 表名(欄位名);
洗掉索引:drop index 索引名 on 表名;

舉例:
在這里插入圖片描述
【索引的底層原理】:跳過吧,這個我也不會,如果有比較好的,能把底層原理講透,講通俗化的博客,麻煩告知我一下,十分感謝,


二十七、視圖(了解)

回到目錄

視圖這一節的話,和前面索引的關系不大,索引是為了提高檢索效率,視圖則是為了資料的保密性,

1)什么是視圖?
視圖就是將一個DQL陳述句的查詢結果作為一張“虛擬表”,可以通過這張虛擬表來 增刪改 原表的資料

2)怎么創建視圖?怎么洗掉視圖?

創建視圖:create view 視圖名 as select 欄位名 from 表名;
洗掉視圖:drop view 視圖名;

3)視圖有什么作用?
你可能會疑惑,直接操作原表不可以嗎,為什么還要創建一個視圖來修改?其實有些表的保密性是比較高的,假如一張表來存盤用戶資訊,其中包括了身份證、銀行卡號等重要資訊,當銀行需要某公司來接手維護他們的用戶管理系統時,為了這些用戶的隱私資訊不被泄漏,就創建視圖,把隱私資訊去除,留下一些不重要的資訊作為一張虛擬表就行,

4)演示視圖

-- 為了不修改emp表,我們先復制emp表
create table emp1 as select * from emp; 
-- 根據emp1表來創建一個視圖
create view myview as select empno,ename,sal from emp1;
-- 通過視圖修改原表資料
delete from myview where empno = 1000;


二十八、資料庫的匯入匯出

回到目錄

在windows的dos命令視窗中執行:

將資料庫中的資料匯出:
mysqldump bjpowernode>E:\bjpowernode.sql -uroot -proot; -- 匯出整個資料庫
mysqldump bjpowernode emp>E:\bjpowernode.sql -uroot -proot; -- 匯出表

匯入資料:
source E:\bjpowernode.sql

mysqldump是匯出命令,bjpowernode是資料庫,> 表示匯出到哪個位置


二十九、設計三范式

回到目錄

什么是設計三范式?
設計三范式是一種規范,讓我們在設計表的時候,能夠避免資料的冗余,減小空間開銷

第一范式:任何一張表都應該有主鍵,并且每一個欄位原子性不可再分
第二范式:在第一范式基礎上,所有非主鍵的欄位完全依賴主鍵,不能產生部分依賴
第三范式:在第二范式基礎上,所有非主鍵欄位直接依賴主鍵,不能產生傳遞依賴

接下來,我們來了解各個范式,

第一范式
我們來看下面這一張表,顯然不符合第一范式.首先這張表沒有主鍵;其次,聯系方式不具有原子性,因為還可以分為郵箱和手機號,

修改如下,即可滿足第一范式


第二范式
下面這張表,不滿足第二范式,原因是主鍵是復合主鍵,即由學生編號和教師編號這兩個欄位構成一個主鍵,這就產生了部分依賴,
它們共同構成主鍵,但是學生姓名卻只依賴于學生編號,不依賴于教師編號;同樣的,教師姓名只依賴于教師編號,不依賴于學生編號,這就是部分依賴,

修改如下,即可滿足第二范式,


對于上面三個表,你可能會有點懵逼,你先記住一下口訣:
【多對多,三張表,關系表兩個外鍵】:如何理解呢?為滿足第二范式,我們將表拆成三個表,第三個表是關系表,多對多是指欄位的關系,多個學生對應多個老師,或者反過來說,多個老師對應多個學生也行,記住了這個口訣,我們以后在設計表的時候,就不需要多加思索,


第三范式
下面這張表,不滿足第三范式,原因是存在傳遞依賴,班級名稱依賴于班級編號,而班級編號依賴于學生編號(因為班級編號屬于學生的一個資訊),這就是傳遞依賴,

修改如下,即可滿足第三范式:


【一對多,兩張表,多的表加外鍵】:同樣是一個口訣,一個班級對應多個學生,這就是一對多的關系,此時需要給多的表(學生表)加外鍵,關聯到班級表,


以上就是三個范式,很好理解,主要記住三范式是為了減少資料冗余,
另外,在實際開發中,我們不一定會使用三范式來設計表,因為多表查詢存在笛卡爾積,查詢效率較慢,所以有時候
會通過犧牲空間(資料大量冗余),來保證查詢效率高,


三十、作業題

回到目錄

在這些練習題中,每一道題都會有不同的解法,

(1)取得每個部門最高薪水的人
(2)哪些人的薪水在部門的平均薪水之上或等于平均薪水的
(3)取得部門中(所有人的)平均的薪水等級
(4)不準用分組函式(max),取得最高薪水
(5)取得平均薪水最高的部門的部門編號(兩種解決方案)
(6)取得平均薪水最高的部門的部門名稱
(7)求平均薪水的等級最低的部門的部門名稱
(8)取得比普通員工(員工代碼沒有在mgr欄位上出現的)的最高薪水還要高領匯入的姓名
(9)取得薪水最高的前五名員工
(10)取得薪水最高的第六到第十名員工
(11)取得最后入職的5名員工
(12)取得每個薪水等級有多少員工
(13)面試題
(14)列出所有員工及領導的姓名
(15)列出受雇日期早于其直接上級的所有員工的編號,姓名,部門名稱
(16)列出部門名稱和這些部門的員工資訊
(17)列出至少有 5 個員工的所有部門
(18)列出薪金比"張飛" 多的所有員工資訊
(19)列出所有 “銷售員” 的姓名及其部門名稱, 部門的人數
(20)列出最低薪金大于 1500 的各種作業及從事此作業的全部雇員人數
(21)列出在部門"銷售部"作業的員工的姓名, 假定不知道銷售部的部門編號
(22)列出薪金高于公司平均薪金的所有員工, 所在部門, 上級領導, 雇員的工資等級
(23)列出與"張三" 從事相同作業的所有員工及部門名稱
(24)列出薪金等于部門 30 中員工的薪金的其他員工的姓名和薪金
(25)列出薪金高于在部門 30 作業的所有員工的薪金的員工姓名和薪金. 部門名稱
(26)列出在每個部門作業的員工數量, 平均工資和平均服務期限
(27)列出所有員工的姓名、部門名稱和工資
(28)列出所有部門的詳細資訊和人數
(29)列出各種作業的最低工資及從事此作業的雇員姓名
(30)列出各個部門的領導的最低薪金
(31)列出所有員工的 年工資, 按 年薪從低到高排序
(32)求出員工領導的薪水超過3000的員工名稱與領導
(33)求出部門名稱中, 帶’財’字符的部門員工的工資合計、部門人數
(34)給任職日期超過 30 年的員工加薪 10%.


1)取得每個部門最高薪水的人

回到練習題目錄

我們先查出部門及對應最高薪水,將其作為一張表,和emp表連接查詢

SELECT
	e1.ename,t.*
FROM
	emp e1
JOIN
	(SELECT
		d.dname,MAX(sal) maxsal
	FROM
		emp e2
	JOIN
		dept d
	ON
		e2.deptno = d.deptno
	GROUP BY
		e2.deptno) t
ON
	e1.sal = t.maxsal;

2)哪些人的薪水在部門的平均薪水之上或等于平均薪水的

回到練習題目錄

與題1類似,先將各部門的平均薪水查出來,作為一張表 t ,再和 emp 表連接

SELECT
	e.ename,t.*,e.sal
FROM
	emp e
JOIN
	(SELECT
		d.deptno,d.dname,AVG(e.sal) avgsal
	FROM
		emp e
	JOIN
		dept d
	ON
		e.deptno = d.deptno
	GROUP BY
		e.deptno) t
ON
	e.sal >= t.avgsal AND e.deptno = t.deptno;


3)取得部門中(所有人的)平均的薪水等級

回到練習題目錄

這道題如果你用了前兩道題類似的做法,先查出所有人的薪水等級,然后作為一張表,與dept表連接查詢的話,那你就中計了,和我一樣,我剛開始也是這么寫的,如下:

SELECT
	d.dname,AVG(t.grade) avggrade 
FROM
	dept d
JOIN
	(SELECT
		e.deptno,e.ename,s.grade 
	FROM
		emp e
	JOIN
		salgrade s
	ON
		e.sal BETWEEN s.losal AND s.hisal) t
ON
	d.deptno = t.deptno
GROUP BY
	t.deptno;

這道題不需要這么麻煩,

-- 大家先復制上面這一段,看看得到了什么表
SELECT
	e.deptno,AVG(s.grade)
FROM
	emp e
JOIN
	salgrade s
ON
	e.sal BETWEEN s.losal AND s.hisal
GROUP BY
	e.deptno;

-- 再連接dept就行
SELECT
	d.dname,AVG(s.grade) avggrede 
FROM
	emp e
JOIN
	salgrade s
ON
	e.sal BETWEEN s.losal AND s.hisal
JOIN
	dept d
ON
	e.deptno = d.deptno
GROUP BY
	e.deptno;

4)不準用分組函式(max),取得最高薪水

回到練習題目錄

使用 limit 和 排序

select ename,sal 最高薪水 from emp order by sal desc limit 0,1;

5)取得平均薪水最高的部門的部門編號(兩種解決方案)

回到練習題目錄

-- 方式一
SELECT deptno FROM emp GROUP BY deptno ORDER BY AVG(sal) DESC LIMIT 0,1; 

-- 方式二
SELECT AVG(sal) avgsal FROM emp GROUP BY deptno; -- 第一步:查出各部門的平均工資
SELECT MAX(t.avgsal) FROM (SELECT AVG(sal) avgsal FROM emp GROUP BY deptno) t; -- 第二步:將第一步中的結果作為一張表,查出最大的那個平均值
SELECT deptno FROM emp GROUP BY deptno HAVING AVG(sal) = (SELECT MAX(t.avgsal) FROM 
(SELECT AVG(sal) avgsal FROM emp GROUP BY deptno) t); -- 第三步:根據deptno分組查詢emp表,將工資
-- 平均值等于第二步中查出的最大平均值的那個部門編號查出來

6)取得平均薪水最高的部門的部門名稱

回到練習題目錄

這道簡單,我們先 SELECT AVG(sal) FROM emp e GROUP BY e.deptno ORDER BY AVG(sal) DESC LIMIT 0,1; 得出最大的部門工資平均值,然后去連接 dept 表得到部門名稱,稍作修改即可,
注意這道題和第三題一樣,沒有必要將結果作為一張新表,直接連接dept表即可,

SELECT
	d.dname
FROM
	emp e
JOIN
	dept d
ON
	e.deptno = d.deptno
GROUP BY
	e.deptno
ORDER BY 
	AVG(sal) DESC
LIMIT 0,1;

7)求平均薪水的等級最低的部門的部門名稱

回到練習題目錄

這道太難,建議跳過

-- 先找出每個部門的平均薪水
select deptno,avg(sal) as avgsal from emp group by deptno;
-- 找出每個部門的平均薪水的等級 (1)
SELECT
	t.*,s.grade
FROM
	(SELECT e.deptno,AVG(sal) avgsal FROM emp e GROUP BY e.deptno) t
JOIN
	salgrade s
ON
	t.avgsal BETWEEN s.losal AND s.hisal;
-- 找出每個部門的平均薪水中的最低的等級 (2)
select grade from salgrade where (select avg(sal) as avgsal from emp group by deptno order by
 avgsal asc limit 1) between losal and hisal;
-- (1) 和 (2) 聯立,再稍作修改
SELECT
	t.dname,s.grade
FROM
	(SELECT d.dname,e.deptno,AVG(sal) avgsal FROM emp e JOIN dept d ON e.deptno = d.deptno GROUP BY e.deptno) t
JOIN
	salgrade s
ON
	t.avgsal BETWEEN s.losal AND s.hisal	
WHERE
	grade = (SELECT grade FROM salgrade WHERE (SELECT AVG(sal) AS avgsal FROM emp GROUP BY deptno ORDER BY avgsal ASC LIMIT 1) BETWEEN losal AND hisal);


8)取得比普通員工(員工代碼沒有在mgr欄位上出現的)的最高薪水還要高領匯入的姓名

回到練習題目錄

-- 第一步:找出不重復的mgr
select distinct mgr from emp;
-- 第二步:找出普通員工中的最高工資
-- 注意不重復的mgr多了個條件,is not null,這是因為如果 not in 后面的小括號中如果有null,
-- 那么結果也會是null,大家可以去掉看看效果
SELECT MAX(sal) FROM emp WHERE empno NOT IN (SELECT DISTINCT mgr 
FROM emp WHERE mgr IS NOT NULL);
-- 第三步:找出所有領導及對應工資
SELECT ename,sal FROM emp WHERE empno IN (SELECT DISTINCT mgr 
FROM emp WHERE mgr IS NOT NULL);
-- 第四步:將第二步和第三步聯立
SELECT ename,sal FROM emp WHERE empno IN 
(SELECT DISTINCT mgr FROM emp WHERE mgr IS NOT NULL)
HAVING sal > (SELECT MAX(sal) FROM emp WHERE empno NOT IN 
(SELECT DISTINCT mgr FROM emp WHERE mgr IS NOT NULL));


9)取得薪水最高的前五名員工

回到練習題目錄

這道,送分題

select ename,sal from emp order by sal desc limit 0,5;

10)取得薪水最高的第六到第十名員工

回到練習題目錄

select enaem,sal from emp order by sal desc limit 5,5;

11)取得最后入職的5名員工

回到練習題目錄

SELECT * FROM emp ORDER BY hiredate DESC LIMIT 0,5;

12)取得每個薪水等級有多少員工

回到練習題目錄

-- 方法一
SELECT 
	t.grade,COUNT(t.grade) 
FROM 
	(SELECT e.ename,s.grade FROM emp e JOIN salgrade s ON e.sal BETWEEN s.losal AND s.hisal) t 
GROUP BY 
	t.grade;

-- 方法二
select
	s.grade,count(*)
from 
	emp e
join
	salgrade s
on
	e.sal between s.losal and s.hisal
group by
	s.grade;

13)面試題【這道題不做,等到jdbc中講】

回到練習題目錄

有3個表s(學生表),c(課程表),sc(學生選課表)
s(sno,sname)代表(學號,姓名)
c(cno,cname,cteacher)代表(課號,課名,教師)
sc(sno,cno,scgrade)代表(學號,課號,成績)
問題:
1)找出沒選過“黎明”老師的所有學生姓名
2)列出2門以上(含2門)不及格學生姓名及平均成績
3)即學過1號課程又學過2號課程的所有學生的姓名
請用標準 SQL 語言寫出答案,方言也行(請說明是使用什么方言)



14)列出所有員工及領導的姓名

回到練習題目錄

這道題注意左連接就好了,因為懂事長是沒有領導的,需要左連接,否則會顯示不了董事長這條記錄,這一點在連接中都有講到,

SELECT 
	e1.ename AS 員工,e2.ename AS 領導 
FROM 
	emp e1 
LEFT JOIN 
	emp e2 
ON
	e1.mgr = e2.empno;

15)列出受雇日期早于其直接上級的所有員工的編號,姓名,部門名稱

回到練習題目錄

SELECT
	e1.ename 員工,e1.hiredate 員工入職日期,e2.ename 領導,e2.hiredate 領匯入職日期
FROM
	emp e1
JOIN
	dept d
ON
	e1.deptno = d.deptno
LEFT JOIN
	emp e2
ON
	e1.mgr = e2.empno
WHERE
	e1.hiredate < e2.hiredate;


16)列出部門名稱和這些部門的員工資訊

回到練習題目錄

SELECT
	d.dname,e.ename
FROM
	dept d
JOIN
	emp e
ON
	d.deptno = e.deptno
ORDER BY
	dname;

17)列出至少有 5 個員工的所有部門

回到練習題目錄

SELECT
	d.dname
FROM
	dept d
JOIN
	emp e
ON
	d.deptno = e.deptno
GROUP BY
	d.dname
HAVING 
	COUNT(*) >= 5;

18)列出薪金比"張飛" 多的所有員工資訊

回到練習題目錄

SELECT
	*
FROM
	emp
WHERE
	sal > (SELECT sal FROM emp WHERE ename = '張飛');

19)列出所有 “銷售員” 的姓名及其部門名稱, 部門的人數

回到練習題目錄

由于我的資料和視頻有些不同,查詢結果不同,這道題如果以下的sql看不懂的話,建議看視頻:點我看視頻

SELECT
	e.ename,e.job,d.dname,t.*
FROM
	emp e
JOIN
	dept d
ON
	e.deptno = d.deptno
JOIN
	(SELECT
		COUNT(*) 銷售部人數
	FROM
		emp e
	JOIN
		dept d
	ON
		e.deptno = d.deptno
	WHERE
		d.dname = '銷售部') t
WHERE
	e.job = '銷售員';

20)列出最低薪金大于 1500 的各種作業及從事此作業的全部雇員人數

回到練習題目錄

SELECT
	job,COUNT(*)
FROM
	emp
GROUP BY
	job
HAVING
	MIN(sal) > 1500;

21)列出在部門"銷售部"作業的員工的姓名, 假定不知道銷售部的部門編號

回到練習題目錄

SELECT ename FROM emp WHERE deptno = (SELECT deptno FROM dept WHERE dname = '銷售部');

22)列出薪金高于公司平均薪金的所有員工, 所在部門, 上級領導, 雇員的工資等級

這道題簡單,一步一步寫就好了,但是是一道好題,綜合性較強,

回到練習題目錄

-- 公司平均薪金
SELECT AVG(sal) FROM emp

-- 高于平均薪金的所有員工
SELECT 
	e.ename
FROM 
	emp e
WHERE 
	e.sal > (SELECT AVG(sal) FROM emp);

--所在部門(內連接),上級領導(自連接+左連接),工資等級(內連接),結果如下
SELECT 
	e1.ename,d.dname,e2.ename,s.grade 
FROM 
	emp e1 
JOIN 
	dept d 
ON 
	e1.deptno = d.deptno 
LEFT JOIN 
	emp e2 
ON 
	e1.mgr = e2.empno 
JOIN 
	salgrade s 
ON 
	e1.sal BETWEEN s.losal AND s.hisal 
WHERE 
	e1.sal > (SELECT AVG(sal) FROM emp);

23)列出與"張三" 從事相同作業的所有員工及部門名稱

回到練習題目錄

SELECT
	e.ename,d.dname
FROM
	emp e
JOIN
	dept d
ON
	e.deptno = d.deptno
WHERE
	job = (SELECT job FROM emp WHERE ename = '張三') and e.ename != '張三';

24)列出薪金等于部門 30 中員工的薪金的其他員工的姓名和薪金

回到練習題目錄

這道題讀起來有點拗口,就是說,除部門3之外的員工,如果有薪金等于部門3中某個員工薪金的,就把他的姓名和薪金查出來,

SELECT 
	ename,sal 
FROM 
	emp 
WHERE 
	sal IN (SELECT DISTINCT sal FROM emp WHERE deptno = 3) AND deptno != 3;

25)列出薪金高于在部門 30 作業的所有員工的薪金的員工姓名和薪金. 部門名稱

回到練習題目錄

SELECT 
	e.ename,e.sal 
FROM 
	emp e 
JOIN 
	dept d 
ON 
	e.deptno = d.deptno 
WHERE 
	sal > (SELECT MAX(sal) FROM emp WHERE deptno = 3);

26)列出在每個部門作業的員工數量, 平均工資和平均服務期限

回到練習題目錄

這道題重點是掌握如何計算兩個日期的“年差”,差了多少年,
函式及格式:timestampdiff(間隔型別,前一個日期,后一個日期)

-- 前面這句不難,主要是掌握后面的平均服務期限,就是 當前日期-入職日期
SELECT 
	e.deptno,d.dname 部門,d.loc,COUNT(*) 員工數量,AVG(sal) 平均工資 
FROM 
	emp e 
JOIN 
	dept d 
ON 
	e.deptno = d.deptno 
GROUP BY 
	e.deptno;

-- 平均服務年限
select timestampdiff(year,hiredate,now()) 服務年限 from emp;

-- 接下來就簡單了
SELECT 
	e.deptno,d.dname 部門,d.loc,COUNT(*) 員工數量,AVG(sal) 平均工資,AVG(TIMESTAMPDIFF(YEAR,hiredate,NOW())) 平均服務年限
FROM 
	emp e 
JOIN 
	dept d 
ON 
	e.deptno = d.deptno 
GROUP BY 
	e.deptno;


27)列出所有員工的姓名、部門名稱和工資

回到練習題目錄

送分題

select 
	e.ename,d.dname,e.sal
from
	emp e
join 
	dept d
on
	e.deptno = d.deptno;

28)列出所有部門的詳細資訊和人數

回到練習題目錄

SELECT
	d.deptno,d.dname,d.loc,COUNT(e.ename)
FROM
	dept d
JOIN
	emp e
ON
	d.deptno = e.deptno
GROUP BY
	d.deptno;

29)列出各種作業的最低工資及從事此作業的雇員姓名

回到練習題目錄

SELECT
	e.ename,t.*
FROM
	emp e
JOIN
	(SELECT job,MIN(sal) minsal FROM emp GROUP BY job) t
ON
	e.sal = t.minsal and e.job = t.job;

30)列出各個部門的領導的最低薪金

回到練習題目錄

各個部門的領導,就把經理算進來就好了,理論上懂事長不屬于某個部門,

select
	deptno,min(sal)
from
	emp
where
	job = '經理'
group by
	deptno;

31)列出所有員工的 年工資, 按 年薪從低到高排序

回到練習題目錄

年工資包括津貼,注意使用 ifnull() 函式

SELECT
	ename,(sal+IFNULL(comm,0))*12 年薪
FROM
	emp
ORDER BY
	年薪 ASC;

32)求出員工領導的薪水超過3000的員工名稱與領導

回到練習題目錄

SELECT
	a.ename 員工,b.ename 領導
FROM
	emp a
JOIN
	emp b
ON
	a.mgr = b.empno
WHERE
	b.sal > 3000;

33)求出部門名稱中, 帶’財’字符的部門員工的工資合計、部門人數

模糊查詢 用like

回到練習題目錄

SELECT
	t.dname,SUM(sal),COUNT(*)
FROM
	emp e
JOIN
	(SELECT deptno,dname FROM dept WHERE dname LIKE '%財%') t
ON
	e.deptno = t.deptno
GROUP BY
	e.deptno;

34)給任職日期超過 30 年的員工加薪 10%.

回到練習題目錄

UPDATE emp SET sal = sal*1.1 WHERE TIMESTAMPDIFF(YEAR,hiredate,NOW()) > 30;

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/159606.html

標籤:其他

上一篇:在Allegro中放置的元件顯示不出來

下一篇:JDBC

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more