MySQL基礎[本人複習時的記錄,適合有基礎的朋友複習回顧]

MySQL基礎

00概述

0-1MySQL初步理解

在這裏插入圖片描述

0-2數據庫存儲數據的特點

在這裏插入圖片描述

0-3MySQL服務的停止與啓動

在這裏插入圖片描述

0-4MySQL服務端的登陸與退出

在這裏插入圖片描述

0-5查看MySQL服務端的版本

在這裏插入圖片描述

0-6MySQL的常見指令

在這裏插入圖片描述

0-7MySQL語法規範

在這裏插入圖片描述

01DQL(Data Query Language)數據查詢語言【具體看代碼部分】

1-1基礎查詢

在這裏插入圖片描述
代碼如下:

/*
語法:select 查詢列表 from 表名;
特點:
1、查詢列表可以是:表中的字段、常量值、表達式、函數
2、查詢的結果是一個虛擬的表格
*/
USE myemployees;
#1、查詢表中的單個字段
SELECT employee_id FROM employees;
#查詢表中的多個字段
SELECT last_name,first_name FROM employees;
#查詢表中的所有字段
SELECT * FROM employees;
#2、查詢常量值
SELECT 'abcdefghijk',100;
#3、查詢表達式
SELECT 100%99;
#4、查詢函數
SELECT VERSION();
/*
5、起別名:
①便於理解
②如果要查詢的字段有重名的情況,使用別名可以區分開來
*/
#方式一:使用as
SELECT last_name AS,first_name ASFROM employees;
#方式二:使用空格
SELECT last_name 姓,first_name 名 FROM employees;
SELECT 100*50 AS "out put";
#6、去重
SELECT DISTINCT department_id FROM employees;
/*
7、+ 的作用(mysql中的+,只有一個功能:作運算符)
①只要有一方爲字符型,那麼試圖將字符型轉換爲數值型,再做運算
轉換成功:繼續做加法運算。	     select '90'+10;結果是100
轉換失敗:將字符值默認爲0,再作運算。select 10+'jhon'+90;結果是100
②只要有一方爲null,做運算後的結果是null。
select 10+90+null;結果是null
*/
#8、拼接:應用函數concat()
SELECT CONCAT(last_name,first_name) AS '姓名' FROM employees;
#9、ifnull()函數
SELECT IFNULL(commission_pct,0) FROM employees;#如果commission_pct是null,就將其更換爲0。
SELECT CONCAT(`first_name`,`last_name`,`job_id`,IFNULL(commission_pct,0)) AS "out put" FROM employees;

1-2條件查詢

在這裏插入圖片描述
代碼如下:

/*
語法:
select
	查詢列表③
from
	表名①
where
	篩選條件;②
*/
/*
分類:
一、按條件表達式篩選
簡單的條件運算符:> ,< ,<>(!=) ,= ,>= ,<=

二、模糊查詢(複雜的條件運算符)
like
between and
in
is null/is not null

三、按邏輯表達式篩選
邏輯運算符(用於連接條件表達式):and(&&) ,or(||) ,not(!)
*/


#【一、按條件表達式查詢:(查詢部門編號不等於80的員工信息)】
SELECT * FROM employees WHERE department_id<>80;
#【二、按邏輯表達式篩選:(查詢部門編號不屬於90-110的員工信息)】
SELECT * FROM employees WHERE NOT(90<=department_id && department_id<=110);
/*
【三、模糊查詢】
通配符:
%:表示任意多個字符
_:表示任意一個字符
*/
#▲▲1、like
#查詢員工姓名中包含字符a的員工信息
SELECT * FROM employees WHERE first_name LIKE '%a%' AND last_name LIKE '%a%';
#轉義字符的使用(查詢員工姓中第二個字母是下劃線_的員工信息)
SELECT * FROM employees WHERE last_name LIKE '_\_%';
SELECT * FROM employees WHERE last_name LIKE '_*_%' ESCAPE '*';
#▲▲2、between and的使用(①包含臨界值②between and涉及的兩個值不可以更換順序[因爲相當於>=前者且<=後者])
#查詢員工編號在100-120之間的員工信息
SELECT * FROM employees WHERE employee_id BETWEEN 100 AND 120;
#▲▲3、in關鍵字的使用(判斷某字段的值是否屬於列表中的某一項)
#等價於job_id='AD_PRES' or job_id='AD_VP'所以in列表中不可以用通配符
SELECT * FROM employees WHERE job_id IN ('AD_PRES','AD_VP');
#▲▲4、is null 和 is not null的使用(判斷某一字段的值是否爲null不可以用=和<>)
#①安全等於<=>既可以判斷null值又可以判斷數值,但是可讀性差
#查詢獎金率爲null的員工信息
SELECT * FROM employees WHERE commission_pct IS NULL;
SELECT * FROM employees WHERE commission_pct <=> NULL;
#▲▲5、isnull()函數(如果爲null返回1,非null返回0)
SELECT commission_pct,ISNULL(commission_pct) FROM employees;

1-3排序查詢

在這裏插入圖片描述
代碼如下:

/*
語法:
select
	查詢列表
from
	表
[where 篩選條件]
order by 排序列表 [asc(升序)/desc(降序)]
特點:
	①如果不寫asc或者desc默認是asc
	②可以按照單個字段、多個字段、函數、表達式、別名排序
	③order by子句一般是放在查詢語句的最後面,limit子句除外
*/
#【按照單個字段排列】查詢員工信息,按照工資從高到低順序排列
SELECT * FROM employees ORDER BY salary DESC;
#【按照表達式排列】查詢員工信息,按照年薪降序排列
SELECT *,salary*12*(1+IFNULL(commission_pct,0)) AS 年薪 FROM employees ORDER BY salary*12*(1+IFNULL(commission_pct,0)) DESC;
#【按照別名排列】order by後面的年薪不可以用引號引起來
SELECT *,salary*12*(1+IFNULL(commission_pct,0)) AS 年薪 FROM employees ORDER BY 年薪 DESC;
#【按照函數排列】按照姓氏長度顯示員工信息
SELECT *,LENGTH(last_name) FROM employees ORDER BY LENGTH(last_name) DESC;
#【按照多個字段排列】查詢員工信息,先【主】按照工資排序(降序),再【次】按照員工編號排序(升序)
SELECT * FROM employees ORDER BY salary DESC,employee_id ASC;
#查詢員工信息,先【主】按照員工編號排序(升序),再【次】按照工資排序(降序)
SELECT * FROM employees ORDER BY employee_id ASC,salary DESC;

1-4常見函數

1-4-1單行函數之字符函數

在這裏插入圖片描述

1-4-2單行函數之數學函數

在這裏插入圖片描述

1-4-3單行函數之日期函數

在這裏插入圖片描述

1-4-4單行函數之其它函數

在這裏插入圖片描述

1-4-5單行函數之流程控制函數

在這裏插入圖片描述

1-4-6分組函數(聚合函數、統計函數、組函數)

在這裏插入圖片描述

1-4-7代碼展示

/*
常見函數:
調用:select 函數名(實參列表)[from 表名]
分類:
1、單行函數:(字符函數、數學函數、日期函數、其他函數、流程控制函數)
例如:concat、length、ifnull、isnull
2、分組函數(功能:做統計使用,又稱爲統計函數、聚合函數、組函數)
*/
#▲▲▲▲▲▲▲▲▲▲▲▲▲【單行函數】▲▲▲▲▲▲▲▲▲▲▲▲▲
#【字符函數】
#1、length 獲取參數值所佔的字節個數
SELECT LENGTH('周逸PM');#8個字節
#2、concat 拼接字符串
SELECT CONCAT(last_name,'_',first_name) AS 姓名 FROM employees;
#3、upper、lower
SELECT UPPER('jhon');
SELECT LOWER('JHon');
#4、substr、substring(SQL語句的索引都是從1開始)
#兩個參數:1:字符串 2:起始位置(截取從起始位置及其之後的所有字符串)
SELECT SUBSTR("一日難再晨",3);#難再晨
#三個參數:1:字符串2:起始位置3:要截取的長度
SELECT SUBSTR("一日難再晨",3,2);#難再
#5、instr(兩個參數:1:字符串2:子串)[返回子串在原串中第一次出現的索引,未找到則返回0]
SELECT INSTR("一日難再晨","難再晨") AS out_put;#3
#6、trim
SELECT TRIM('   難再晨   ');
SELECT TRIM('a' FROM 'aaaaaaaaa難再晨aaaaaaaaaa') AS result;
#7、lpad、rpad(三個參數:1:字符串2:填充後的總長度3:填充字符)
#[如果填充的總長度小於原字符串長度,則按參數2的值,從左向右按指定填充後的總長度截取原串並返回]
SELECT LPAD('難再晨',5,'l');
SELECT RPAD('難再晨',5,'r');
#8、replace 替換(三個參數1:原串2:將被替換的串3:替換串)
SELECT REPLACE('及時難再晨,難再晨,難再晨,難再晨','難再晨','當勉勵') AS result;
#【數學函數】
#1、round 四捨五入
SELECT ROUND(1.445656);#1
#兩個參數2:小數點後保留的位數
SELECT ROUND(1.445656,3)#1.446
#2、ceil 向上取整
SELECT CEIL(-1.2);#-1
#3、floor 向下取整
SELECT FLOOR(-1.2);#-2
#4、truncate 截斷(2:小數點後保留的位數,在其後的截去)
SELECT TRUNCATE(-1.2435232,3);#-1.243
#5、mod 取餘數(相當於計算a % b)
SELECT MOD(-10,-3);#-1
#【日期函數】
#1、now 返回當前系統的日期+時間
SELECT NOW();
#2、curdate 返回當前系統日期,不返回時間
SELECT CURDATE();
#3、curtime 返回當前系統時間,不返回日期
SELECT CURTIME();
#4、可以獲取指定的部分(年、月、日、時、分、秒)
SELECT YEAR(CURDATE());
SELECT MONTH('1999-2-5');
SELECT YEAR(hiredate) FROM employees;
SELECT MONTHNAME('1999-2-5');#February
/*
5、str_to_date 將日期格式的字符轉換成指定格式的日期

%Y-四位的年份;%y-兩位的年份;%m-月份(01,02...);%c-月份(1,2...);%d-日(01,02...)
%H-小時(24小時制);%h-小時(12小時制);%i-分鐘(00,01...59);%s-秒(00,01...59)
*/
SELECT STR_TO_DATE('1998-02-3-13','%Y-%m-%d-%H');
#查詢入職日期爲1992-4-3的員工信息
SELECT * FROM employees WHERE hiredate='1992-4-3';
SELECT * FROM employees WHERE hiredate=STR_TO_DATE('3-04++1992','%d-%m++%Y');
#6、date_format 將日期轉換成字符
SELECT DATE_FORMAT(hiredate,'(%c月%d日)-[%Y年]') FROM employees;
#【其他函數】
SELECT VERSION();
SELECT USER();
SELECT DATABASE();
#【流程控制函數】
#1、if函數:實現if-else效果,(類似於三元運算符)
SELECT commission_pct,IF(commission_pct IS NULL,'沒有獎金','有') AS 備註 FROM employees;
/*
2、case函數
語法:
case 字段或表達式
when 常量1 then 要顯示的值1或者語句1
when 常量2 then 要顯示的值2或者語句2
...
else 要顯示的值n或者語句n
end
*/
/*
查詢員工工資,要求
部門號=30,顯示工資爲1.1倍
部門號=40,顯示工資爲1.2倍
部門號=50,顯示工資爲1.3倍
*/
SELECT salary 原工資,department_id,
CASE department_id
WHEN 30 THEN salary*1.1
WHEN 40 THEN salary*1.2
WHEN 50 THEN salary*1.3
ELSE salary
END AS 新工資
FROM employees;
/*
case函數的使用二:
case
when 條件1 then 要顯示的值1或者語句1
...
else 要顯示的值n或者語句n
end
*/
/*
查詢員工的工資情況
工資>20000.A
工資>15000,B
工資>10000,C
否則,D
*/
SELECT salary AS 工資,
CASE
WHEN salary>20000 THEN 'A'
WHEN salary>15000 THEN 'B'
WHEN salary>10000 THEN 'C'
ELSE 'D'
END AS 級別
FROM employees;


#▲▲▲▲▲▲▲▲▲▲▲▲▲【分組函數】▲▲▲▲▲▲▲▲▲▲▲▲▲
/*分類:sum 求和、avg 平均、max 最大、min 最小、count 計算個數(計算的字段非null的行數)
1、sum avg 一般用來處理數值型
max min count 可以用來處理任何類型
2、以上分組函數都忽略null值
*/
SELECT SUM(salary) 總工資,ROUND(AVG(salary),2) 平均工資,MAX(salary) 最高工資,
COUNT(commission_pct) 獎金率非null的人數
FROM employees;
#與distinct搭配實現去重的運算
SELECT SUM(DISTINCT salary),SUM(salary) FROM employees;
SELECT COUNT(DISTINCT salary),COUNT(salary) FROM employees;
#count的介紹(一般用作統計行數)
SELECT COUNT(*),COUNT(1),COUNT(2),COUNT(salary) FROM employees;
/*
效率:
MYISAM存儲引擎:count(*)的效率高
INNODB存儲引擎:count(*),count(1)效率差不多,比count(字段)效率高一些
*/
#和分組函數一同查詢的字段要求是group by後的字段
#datediff函數(返回兩個date類型日期相差的天數)
SELECT DATEDIFF(NOW(),'1999-1-22');

1-5分組查詢

在這裏插入圖片描述
代碼如下:

/*
【分組查詢:】

語法:
select 分組函數,列(要求出現在group by後面)
from 表名
[where 篩選條件]
group by 分組的列表
[order by 子句]

注意:
分組的列表必須是group by後面出現的字段
*/
#簡單的分組查詢
#案例1:查詢每個工種的最高工資
SELECT MAX(salary),job_id
FROM employees
GROUP BY job_id;
#案例2:統計每個位置的部門個數
SELECT location_id,COUNT(*)
FROM departments
GROUP BY location_id;
#複雜的分組查詢
#▲▲▲▲▲▲添加分組前的篩選【where】
#案例3:查詢有獎金的每個領導手下員工的最高工資
SELECT MAX(salary),manager_id FROM employees WHERE commission_pct IS NOT NULL GROUP BY manager_id;
#▲▲▲▲▲▲添加分組後的篩選條件【having】
/*
案例4:查詢哪個部門的員工個數>2
①查出每個部門的員工個數
②根據①中查詢出的員工個數,判斷哪個>2
注:不能用where count(*)>2判斷,因爲employees表中沒有count(*)這個字段
*/
SELECT COUNT(*),department_id
FROM employees
GROUP BY department_id
HAVING COUNT(*)>2;
#案例5:查詢每個工種有獎金的員工的最高工資>12000的工種編號和最高工資
SELECT MAX(salary),job_id
FROM employees
WHERE commission_pct IS NOT NULL
GROUP BY job_id
HAVING MAX(salary)>12000;
#案例6:查詢領導編號>102的每個領導手下的最低工資>5000的領導編號,以及其最低工資
SELECT manager_id,MIN(salary)
FROM employees
WHERE manager_id>102
GROUP BY manager_id
HAVING MIN(salary)>5000;
#按照函數或者表達式分組
#案例7:按員工姓名長度分組,查詢每一組的員工個數,篩選員工個數>5的有哪些
#mysql中支持group by和having後面放別名,但是oracle等不支持
SELECT LENGTH(last_name),COUNT(*)
FROM employees
GROUP BY LENGTH(last_name)
HAVING COUNT(*)>5;
#按照多個字段分組
#案例8:查詢每個部門每個工種的員工的平均工資
SELECT AVG(salary),department_id,job_id
FROM employees
GROUP BY department_id,job_id;
#添加排序的分組查詢
#案例9:查詢每個部門每個工種的員工的平均工資,並且按平均工資由高到低顯示
SELECT AVG(salary),department_id,job_id
FROM employees
GROUP BY department_id,job_id
ORDER BY AVG(salary) DESC;
#特點:
/*
1、分組查詢中的篩選條件分爲兩類:
			數據源		位置			關鍵字
	分組前篩選	原始表		group by子句前面	where
	分組後篩選	分組後的結果集	group by子句後面	having
	①分組函數做條件肯定放在having子句中
	②能用分組前篩選的就用它,這樣效率高
2、group by子句支持單個字段分組,多個字段分組(多個字段之間用逗號隔開,無順序要求),表達式或函數(用得較少)
3、也可以添加排序(排序放在整個查詢語句的最後)
*/

1-6連接查詢(多表查詢)

在這裏插入圖片描述

1-6-1sql92標準

代碼如下:

/*
連接查詢:
	連接查詢又稱多表查詢,當查詢的字段來自多個表時,使用該查詢
	笛卡爾乘積現象:表1 m行;表2 n行;查詢結果 m*n行
	發生原因:沒有連接條件
	如何避免:添加連接條件
分類:
	①按年代分類:
		sql92標準:僅僅支持內連接
		sql99標準:支持內連接+外連接(左外、右外)+交叉連接
	②按功能分類:
		內連接:等值連接、非等值連接、自連接
		外連接:左外、右外、全外
		交叉連接
*/

#【一、sql92】:內連接:等值、非等值、自
#▲▲▲▲▲▲等值連接
/*
①多表等值連接的結果爲多表的交集部分
②n表連接,至少需要n-1個連接條件
③多表的順序沒有要求
④一般需要爲表起別名
⑤可以搭配前面的所有子句一起使用(如:排序、分組、篩選)
*/
#案例1:查詢女生名和對應的男生名
SELECT `name`,boyName
FROM beauty,boys
WHERE boyfriend_id=boys.`id`;
#案例2:查詢員工名和對應的部門名
SELECT last_name,department_name
FROM employees,departments
WHERE employees.`department_id`=departments.`department_id`;
#2、爲表起別名
/*
①提高語言簡潔度②區分多個重名字段
注:如果起了別名,就不可以用原來的表名去限定
*/
#案例3:查詢員工名、工種號、工種名
SELECT last_name,j.job_id,job_title
FROM employees e,jobs AS j
WHERE e.`job_id`=j.`job_id`;
#加篩選
#查詢有獎金的員工名、部門名
SELECT last_name,department_name
FROM employees e,departments d
WHERE e.`department_id`=d.`department_id`
AND commission_pct IS NOT NULL;
#查詢城市中第二個字符爲o的部門名和城市名
SELECT department_name,city
FROM departments d,locations l
WHERE d.`location_id`=l.`location_id`
AND city LIKE '_o%';
#加分組
#查詢每個城市的部門個數
SELECT city,COUNT(*)
FROM locations l,departments d
WHERE l.`location_id`=d.`location_id`
GROUP BY city;
#查詢有獎金的每個部門的部門名、部門的領導編號和該部門的最低工資
SELECT department_name,d.manager_id,MIN(e.salary)
FROM departments d,employees e
WHERE d.`department_id`=e.`department_id`
AND e.`commission_pct` IS NOT NULL
GROUP BY d.department_id;
#加排序
#查詢每個工種的工種名和員工的個數,按照員工個數降序
SELECT job_title,COUNT(*)
FROM jobs j,employees e
WHERE j.`job_id`=e.`job_id`
GROUP BY e.`job_id`
ORDER BY COUNT(*) DESC;
#查詢員工名、部門名和所在城市
SELECT last_name,department_name,city
FROM employees e,departments d,locations l
WHERE e.`department_id`=d.`department_id`
AND d.`location_id`=l.`location_id`;
#▲▲▲▲▲▲非等值連接
#查詢員工的工資等級爲A的員工的工資和級別
SELECT salary,grade_level
FROM employees e,job_grades j
WHERE salary BETWEEN j.`lowest_sal` AND j.`highest_sal`
AND grade_level='A';
#▲▲▲▲▲▲自連接
#查詢員工名和其領導的名稱
SELECT e.last_name AS 員工,m.last_name AS 領導
FROM employees e,employees m
WHERE e.`manager_id`=m.`employee_id`;

1-6-2sql99標準

代碼如下:

#sql99語法
/*
語法:
	select 查詢列表
	from 表1 別名 [連接類型]
	join 表2 別名
	on 連接條件
	[where 篩選條件]
	[group by 分組]
	[having 篩選條件]
	[order by 排序列表]
分類:
內連接:inner
外連接:左外(left[outer])、右外(right[outer])、全外(full[outer])
交叉連接:cross

*/
#【內連接】:等值連接、非等值連接、自連接
/*
特點:
	①添加排序、分組、篩選
	②inner可以省略
	③篩選條件放在where後面,連接條件放在on後面,提高分離性,便於閱讀
	④inner join連接和sql92語法中的等值連接效果一樣,都是查詢多表的交集
*/

#▲▲▲▲▲等值連接
#案例1:查詢員工名、部門名
SELECT last_name,department_name
FROM employees e
INNER JOIN departments d
ON e.`department_id`=d.`department_id`;
#案例2:查詢名字中包含e的員工名和工種名(添加篩選)
SELECT last_name,job_title
FROM employees e
INNER JOIN jobs j
ON e.`job_id`=j.`job_id`
WHERE last_name LIKE '%e%';
#案例3:查詢每個城市中部門個數大於3的城市(添加分組+篩選)
SELECT city,COUNT(*)
FROM departments d
INNER JOIN locations l
ON d.`location_id`=l.`location_id`
GROUP BY city
HAVING COUNT(*) > 3;
#案例4.查詢哪個部門的員工個數>3的部門名和員工個數,並按個數降序(添加排序)
SELECT department_name,COUNT(*)
FROM employees e
INNER JOIN departments d
ON e.`department_id`=d.`department_id`
GROUP BY d.department_id
HAVING COUNT(*)>3
ORDER BY COUNT(*) DESC;
#5.查詢員工名、部門名、工種名,並按部門名降序
SELECT last_name,department_name,job_title
FROM employees e
INNER JOIN departments d
INNER JOIN jobs j
ON e.`department_id`=d.`department_id` AND e.`job_id`=j.`job_id`
ORDER BY department_name DESC;
#▲▲▲▲▲▲非等值連接
#案例1:查詢員工工資級別
SELECT salary,grade_level
FROM employees e
INNER JOIN job_grades j
ON e.`salary` BETWEEN j.`lowest_sal` AND j.`highest_sal`;
#案例2:查詢工資級別數量>20的個數,並且按工資級別降序
SELECT salary,grade_level,COUNT(*) 級別個數
FROM employees e
INNER JOIN job_grades j
ON e.`salary` BETWEEN j.`lowest_sal` AND j.`highest_sal`
GROUP BY grade_level
HAVING COUNT(*)>20
ORDER BY grade_level DESC;
#▲▲▲▲▲▲自連接
#案例3:查詢員工名和其上級名稱
SELECT e.last_name 員工,m.last_name 經理
FROM employees e
INNER JOIN employees m
ON e.`manager_id`=m.`employee_id`;
#【外連接】
/*
特點:
①外連接的查詢結果爲主表中的所有記錄
	如果有匹配的,則顯示匹配的
	如果沒有匹配的,則顯示null
②左外連接:left join左邊的是主表
右外連接:right join右邊是主表
③一般用不可能爲null的值(主鍵)去作爲篩選條件
*/
#查詢沒有男朋友的女生名稱(左外連接)
SELECT `name`,boyName
FROM beauty be
LEFT OUTER JOIN boys bo
ON be.boyfriend_id = bo.id
WHERE bo.id IS NULL;
#右外連接
SELECT `name`,boyName
FROM boys bo
RIGHT OUTER JOIN beauty be
ON bo.`id`=be.`boyfriend_id`
WHERE bo.`id` IS NULL;
#查詢哪個部門沒有員工
SELECT department_name
FROM departments d
LEFT OUTER JOIN employees e
ON d.`department_id`=e.`department_id`
WHERE e.`employee_id` IS NULL;

#【交叉連接】使用cross join 其實就是99語法實現的笛卡爾乘積
SELECT bo.*,be.*
FROM beauty be
CROSS JOIN boys bo;

1-7子查詢

在這裏插入圖片描述
代碼如下:

/*
含義:
	出現在其他語句中的select語句,稱爲子查詢或內查詢
	外部的查詢語句,稱爲主查詢或外查詢
分類:
	一、按子查詢出現的位置:
		select後面:
			僅僅支持標量子查詢
		from後面:
			支持表子查詢
		where或having後面:★
			標量子查詢(單行)
			列子查詢(多行)
			行子查詢
		exists後面(相關子查詢)
			表子查詢
	二、按結果集的行列數不同:
		標量子查詢(結果集只有一行一列)
		列子查詢(結果集只有一列多行)
		行子查詢(結果集有一行多列)
		表子查詢(結果集一般爲多行多列)
*/

/*一、where或having後面
	1、標量子查詢(單行子查詢)
	2、列子查詢(多行子查詢)
	3、行子查詢
特點:
	①子查詢放在小括號內
	②子查詢一般放在條件的右側
	③標量子查詢,一般搭配着單行操作符使用
	> < >= <= = <>
	列子查詢,一般搭配着多行操作符使用
	in、any/some、 all
	④子查詢的執行優先於主查詢執行,主查詢的條件用到了子查詢的結果
*/
#【一、標量子查詢】
#案例1:誰的工資比Abel高
SELECT last_name,salary
FROM employees
WHERE salary>(
	SELECT salary
	FROM employees
	WHERE last_name='Abel'
);
#案例2:返回job_ id與141號 員工相同,salary比143號員工多的員工姓名,job_ id和工資
SELECT last_name
FROM employees
WHERE job_id=(
	SELECT job_id
	FROM employees
	WHERE employee_id=141
)
AND salary>(
	SELECT salary
	FROM employees
	WHERE employee_id=143
);
#案例3:返回公司工資最少的員工的last_ name, job_ id和salary
SELECT last_name,job_id,salary
FROM employees
WHERE salary=(
	SELECT MIN(salary)
	FROM employees
);
#案例4:查詢最低工資大於50號部門最低工資的部門id和其最低工資
SELECT department_id,MIN(salary)
FROM employees
GROUP BY department_id
HAVING MIN(salary)>(
	SELECT MIN(salary)
	FROM employees
	WHERE department_id=50
);
#【列子查詢(多行子查詢)】(使用in、some/any、all)
#案例1:返回location_ id是1400或1700的部門中的所有員工姓名
SELECT last_name
FROM employees
WHERE department_id IN(
	SELECT department_id
	FROM departments
	WHERE location_id IN(1400,1700)
);
#案例2:返回其它部門中比job_ id爲‘IT_ PROG' 工種任一工資低的員工的員工號、姓名、job__id 以及salary
SELECT employee_id,last_name,job_id,salary
FROM employees
WHERE job_id <> 'IT_PROG'
AND
salary<ANY(
	SELECT salary
	FROM employees
	WHERE job_id = 'IT_PROG'
);
#【行子查詢】
#案例3:查詢員工編號最小並且工資最高的員工信息
#利用行子查詢(where括號後內容,應與select查詢的一致)
SELECT *
FROM employees
WHERE(employee_id,salary)=(
	SELECT MIN(employee_id),MAX(salary)
	FROM employees
);
#不利用行子查詢
SELECT * 
FROM employees
WHERE employee_id=(
	SELECT MIN(employee_id)
	FROM employees
)
AND
salary=(
	SELECT MAX(salary)
	FROM employees
);
#select後面
SELECT(
	SELECT COUNT(*)
	FROM employees e
	WHERE e.department_id=d.department_id
)
FROM departments d;
#from後面(將子查詢結果充當一張表,要求必須起別名)
#查詢每個部門平均工資的工資等級
SELECT avg_tab.*,grade_level
FROM(
	SELECT AVG(salary) AS avg_sa
	FROM employees
	GROUP BY department_id
) AS avg_tab
INNER JOIN job_grades j
ON avg_tab.avg_sa BETWEEN j.`lowest_sal` AND j.`highest_sal`;
#exists後面(相關子查詢)
#查詢有員工的部門名
SELECT department_name
FROM departments d
WHERE EXISTS(
	SELECT * FROM employees e
	WHERE e.`department_id`=d.`department_id`
);
#查詢沒有女朋友的男生信息
SELECT bo.*
FROM boys bo
WHERE bo.id NOT IN (
	SELECT boyfriend_id
	FROM beauty
);

SELECT bo.*
FROM boys bo
WHERE NOT EXISTS(
	SELECT * FROM beauty be
	WHERE bo.`id`=be.`boyfriend_id`
);

SELECT bo.*,be.*
FROM boys bo
LEFT OUTER JOIN beauty be
ON bo.`id`=be.`boyfriend_id`
WHERE be.`boyfriend_id` IS NULL;

1-8分頁查詢

代碼如下:

/*分頁登詢

應用場景:當要顯示的數據,一頁顯示不全,需要分頁提交sql請求
語法:
	select查詢列表
	from表
	join type join 表2
	on連接條件
	where
	篩選條件
	group by分組字段
	having分組後的篩選
	order by排序的字段]
	limit offset,size;

offset要顯示條目的起始索引(起始索引從);size要顯示的條目個數
特點:
	①索引從0開始
	②limit子句放在查詢語句最後
	③公式:
	要查詢的頁數page,每頁的條目數size
	select * from 表名 limit (page-1)*size,size;
	
*/
#案例1:查詢前5條員工的信息
SELECT * FROM employees
LIMIT 0,5;
#(如果查詢的信息是從第一條開始的,起始索引可以省去)
SELECT * FROM employees
LIMIT 5;
#案例2:查詢第11條到第25條員工的信息
SELECT * FROM employees 
LIMIT 10,15;
#案例3:有獎金的員工信息,並且工資較高的前10名顯示出來
SELECT * FROM employees
WHERE commission_pct IS NOT NULL
ORDER BY salary DESC
LIMIT 10;

1-9聯合查詢

在這裏插入圖片描述
代碼如下:

/*聯合查詢
union(聯合、合併):將多條查詢語句的結果合併成一個結果
語法:
	查詢語句1
	union
	查詢語句2
	union
	...
	查詢語句n;
應用場景:
	要查詢的結果來自多個表,且多個表之間沒有直接的連接關係,但查詢的信息一致時
特點:
	1、要求多條查詢語句的列數是一致的
	2、要求多條查詢語句查詢的每一列的類型和順序最好一致
	3、union關鍵字默認去重,如果使用union all 可以包含重複項
*/
#查詢部門編號>90或者郵箱包含a的員工信息(用聯合查詢)
SELECT * FROM employees WHERE department_id>90
UNION
SELECT * FROM employees WHERE email LIKE '%a%';
#查詢部門編號>90或者郵箱包含a的員工信息(不使用聯合查詢)
SELECT * FROM employees WHERE department_id>90 OR email LIKE '%a%';

02DML(Data Manipulation Language)數據操作語言【具體看代碼部分】

2-1插入語句

在這裏插入圖片描述
代碼如下:

/*DML語言(數據操作語言)
插入:insert
修改:update
刪除:delete
*/
/*一、插入語句
語法:
	insert into 表名(字段1,字段2...字段n) values(值1,值2,...值n);
*/
#【一、經典的插入】
SELECT * FROM beauty;
#1、插入值的類型要與列的類型一直或兼容
INSERT INTO beauty(id,NAME,sex,borndate,phone,photo,boyfriend_id)
VALUES(13,'唐藝昕','女','1990-4-23','18832778764',NULL,2);
#2、非Nullable的列必須插入值,Nullable的列如何插入值?
#方式一:顯示輸入null
INSERT INTO beauty(id,NAME,sex,borndate,phone,photo,boyfriend_id)
VALUES(14,'紫琪','女','1990-4-23','18988888723',NULL,9);
#方式二:不輸入null
INSERT INTO beauty(id,NAME,phone) VALUES(15,'娜扎','18347146352');
#3、列的順序可以調換
#4、列的個數和值的個數必須一致
#5、可以省略列名,默認是所有列,而且列的順序和表中列的順序一致
#【二、方式二】
/*
語法:
insert into表名
set 列名=值,列名=值,...
*/
INSERT INTO beauty
SET id=16,NAME='劉濤',phone='999';
#【兩種方式的對比】
#1、方式一支持插入多行,方式二不支持
INSERT INTO beauty
VALUES(23,'唐藝昕1','女','1990-4-23','187222',NULL,2)
,(24,'唐藝昕1','女','1990-4-23','187222',NULL,2)
,(25,'唐藝昕1','女','1990-4-23','187222',NULL,2)
#2、方式一支持子查詢,方式二不支持
INSERT INTO beauty(id,NAME,phone)
SELECT	26,'宋茜','12123';
#
INSERT INTO beauty(id,NAME,phone)
SELECT id,boyName,'123123'
FROM boys WHERE id<3;
#
INSERT INTO beauty(id,NAME,phone)
SELECT 1,'a','123' UNION
SELECT 2,'b','123' UNION
SELECT 3,'c','123' UNION
SELECT 2,'d','123';

2-2修改語句

在這裏插入圖片描述
代碼如下:

#修改語句
/*
1、修改單表的記錄
	語法:update 表名
	     set 列=新值,列=新值...
	     where 篩選條件;
	     
2、修改多表的記錄 
92語法:
	update 表1 別名,表2 別名
	set 列=值,...
	where 連接條件
	and 篩選條件;
99語法:
	update 表1 別名
	inner|left|right join on 表2 別名
	on 連接條件
	set 列=值,...
	where 篩選條件;
*/
#【修改單表的記錄】
#案例1:修改beauty表中姓唐的女生的電話爲13899888899
UPDATE beauty
SET phone='13899888899'
WHERE NAME LIKE '唐%';
#案例2:修改boys表中id爲2的名稱爲張飛,魅力值10
UPDATE boys
SET NAME='張飛',userCP=10
WHERE id=2;
#【修改多表的記錄】
#案例1:修改張無忌的女朋友的手機號爲114
UPDATE boys bo
INNER JOIN beauty be
ON bo.`id`=be.`boyfriend_id`
SET be.`phone`='114'
WHERE bo.`boyName`='張無忌';
#案例2:修改沒有男朋友的女神的男朋友編號都爲2號
UPDATE beauty be
LEFT OUTER JOIN boys bo
ON be.`boyfriend_id`=bo.`id`
SET be.`boyfriend_id`=2
WHERE bo.`id` IS NULL;

2-3刪除語句

在這裏插入圖片描述
代碼如下:

#刪除語句
/*
方式一:delete
語法:
1、單表的刪除
	delete from 表名 where 篩選條件;
2、多表的刪除
sql92語法:
	delete 表1別名,表2別名
	from 表1 別名,表2 別名
	where 連接條件
	and 篩選條件
	
sql99語法:
	delete 表1別名,表2別名
	from 表1 別名
	inner|left outer|right outer join 表2 別名
	on 連接條件
	where 篩選條件
	

方式二:truncate
語法:truncate table 表名;
*/
#【delete】
SELECT * FROM beauty;
#單表的刪除
DELETE FROM beauty WHERE id BETWEEN 13 AND 16;
#多表的刪除:刪除張無忌的女朋友的信息
DELETE be
FROM boys bo
INNER JOIN beauty be
ON bo.`id`=be.`boyfriend_id`
WHERE bo.`boyName`='張無忌';
#案例2:刪除黃曉明和其女朋友的信息(級聯刪除)
DELETE bo,be
FROM boys bo
INNER JOIN beauty be
ON bo.`id`=be.`boyfriend_id`
WHERE bo.`boyName`='黃曉明';

SELECT * FROM beauty;
#【truncate】
#案例1:將魅力值>100的男生信息刪除(truncate後面不可以加where篩選條件,刪除的是整個表)
TRUNCATE TABLE boys;

#【delete VS truncate】
/*
1、delete可以加where條件,truncate不可以加where條件
2、truncate刪除的效率稍高
3、加入要刪除的表中有自增長列,
使用delete刪除後,再插入數據,自增長列的值從斷點處開始
使用truncate刪除後,再插入數據,自增長列的值從1開始
4、truncate刪除沒有返回值,delete刪除有返回值
5、truncate刪除不能回滾,delete刪除可以回滾
*/

03DDL(Data Definition Language)數據定義語言【具體看代碼部分】

由於庫和表的管理所用關鍵字相同,所以需要在關鍵字後面標識DATABASE或TABLE以便區分

3-1庫的管理

在這裏插入圖片描述
代碼如下:

#DDL(數據定義語言)
/*
數據定義語言
庫和表的管理
一、庫的管理
創建、修改、刪除
二、表的管理
創建、修改、刪除

創建:create
修改:alter
刪除:drop
*/
#【庫的管理】
/*
1、庫的創建:
語法:
	create database [if not exists] 庫名;
*/
#1、庫的創建
CREATE DATABASE IF NOT EXISTS book;
#2、庫的修改
#更改字符集
ALTER DATABASE book CHARACTER SET gbk;
#3、庫的刪除DROP DATABASE [if exists] 庫名;
DROP DATABASE book;

3-2表的管理

在這裏插入圖片描述
代碼如下:

#【1、表的創建】
/*
create table [if not exists]表名(
	列名 列類型[(長度) 列的約束],
	列名 列類型[(長度) 列的約束],
	...
	列名 列類型[(長度) 列的約束],
);
*/
#創建book表
CREATE TABLE book(
	id INT,
	bName VARCHAR(20),
	price DOUBLE,
	authorId INT,
	publishDate DATETIME
);
#創建author表
CREATE TABLE author(
	id INT,
	au_name VARCHAR(20),
	nation VARCHAR(20)
);
#【2、表的修改】
/*
①修改表名
②修改列名
③修改列的類型或約束
④添加列
⑤刪除列
*/
#①修改列名alter table 表名 change column 列名 新列名 新類型;[change]
ALTER TABLE book CHANGE COLUMN publishDate pubDate DATETIME;
#②修改列類型或約束alter table 表名 modify column 列名 新類型;[modify]
ALTER TABLE book MODIFY COLUMN pubDate DATETIME;
#③添加新列alter table 表名 add column 新列名 類型 [first|after 列名];
ALTER TABLE author ADD COLUMN annual DOUBLE;
DESC book;
DESC book_author;
#④刪除列alter table 表名 drop column 列名;
ALTER TABLE author DROP COLUMN annual;
#⑤修改表名alter table 表名 rename to 新表名;
ALTER TABLE author RENAME TO book_author;
#【3、表的刪除】drop table [if exists]表名;
/*
通用寫法:
創建庫
drop database if exists 庫名;
create database 庫名;

創建表
drop table if exists 表名;
create table 表名;

*/
#【4、表的複製】
INSERT INTO author
VALUES(1,'村上春樹','日本'),
(2,'莫言','中國'),
(3,'馮唐','中國'),
(4,'金庸','中國');
SELECT * FROM author;
#1、僅複製表的結構create table 新表名 like 表名;
CREATE TABLE copy LIKE author;
#2、複製表的結構+數據
CREATE TABLE copy1
SELECT * FROM author;
#複製部分數據
CREATE TABLE copy2
SELECT * FROM author
WHERE nation='日本';
#複製某些字段(沒有數據)
CREATE TABLE copy3
SELECT id
FROM author
WHERE 1=2;#或者where 0;

3-3常見的數據類型和約束

3-3-1數值型

在這裏插入圖片描述
代碼如下:

#【整型】
/*
分類:
tinyint(1B)、smallint(2B)、mediumint(3B)、int/integer(4B)、bigint(8B)

特點:
①如果不設置無符號或者有符號,默認是有符號,如果想設置無符號,後面需要添加unsigned關鍵字
②如果不設置長度,會有默認的長度
長度代表的是顯示的最小寬度,如果插入的數據不夠該長度,會在左邊填充n個0使其達到指定的長度
但是後面需要追加zerofill.例如:t2 int(1) zerofill(一旦指定了zerofill,代表其一定是無符號的數值)
*/
#1、如何設置有符號和無符號
CREATE TABLE IF NOT EXISTS math(
	t1 INT(1),#默認是有符號,在t1字段插入負數能成功
	t2 INT(10) ZEROFILL#設置爲無符號,不可插入負數,如果插入的爲負數會報異常,並且插入臨界值
);
INSERT INTO math VALUES(-1,-1);
ALTER TABLE math MODIFY t2 INT(5) ZEROFILL;
INSERT INTO math VALUES(123123,2);

SELECT * FROM math;
DROP TABLE math;
#【小數】
/*
一、分類:
1、浮點型
float(M,D)
double(M,D)
2、定點型
dec(M,D)
decimal(M,D)(最大取值範圍與double相同)

二、特點:
①M:整數+小數部分的位數
 D:小數部分的位數

 
②M和D都可以省略
如果是decimal,則M默認爲10,D默認爲0,意味着插入的數據小數點後有位數,則插入失敗
如果是float和double,則會根據插入的數值的精度來決定精度

③定點型的精確度較高,如果要求插入數值的精度較高(如貨幣運算等)則考慮使用
*/
CREATE TABLE IF NOT EXISTS fudian(
	f1 FLOAT(5,2),
	f2 DOUBLE(5,2),
	f3 DECIMAL(5,2),#都代表整數部分3位,小數部分2位
	f4 DEC(5,2)#默認是f4 decimal(10,0)
);

3-3-2日期型

在這裏插入圖片描述
代碼如下:

#日期型
/*
分類:
	date只保存日期
	time只保存時間
	year只保存年
	datetime保存日期+時間
	timestamp保存日期+時間
特點:
		字節		範圍		時區的影響
datetime	8		1000-9999	不受
timestamp	4		1970-2038	受
*/
CREATE TABLE riqi(
	`date` DATETIME,
	`timestamp` TIMESTAMP
);
INSERT INTO riqi VALUES(NOW(),NOW());
#顯示當前的時區
SHOW VARIABLES LIKE 'time_zone';
#設置當前的時區
SET time_zone='+9:00';#東九區比東八區晚一個小時
SELECT * FROM riqi;

3-3-3字符型

在這裏插入圖片描述
代碼如下:

#【字符型】
/*
較短的文本:char、varchar
較長的文本:text、blob(較長的二進制)
其它:binary、varbinary(較短的二進制)
      enum(枚舉)
      set(集合)

特點:char(M)【M:0~255】 VS varchar(M)【M:0~65535】

	寫法		M的意思				特點		空間耗費	效率
char	char(M)		最大的字符數,可以省略,默認爲1	固定長度的字符	比較耗費	高

varchar	varchar(M)	最大的字符數,不可以省略		可變長度的字符	比較節省	低
*/
#【enum】
CREATE TABLE zifu(
	c1 ENUM('a','b','c'),
	c2 SET('a','b','c')
);
INSERT INTO zifu VALUES('A'),#大寫的也可以插入,插入後也是小寫的
('m');#m沒在enum中,插入失敗
#【set】
INSERT INTO zifu(c2) VALUES('a,B,c');#插入成功!

3-3-4常見約束

一、概述
約束:一種限制,用於限制表中的數據,爲了保證表中數據的準確性和可靠性
二、六大約束
在這裏插入圖片描述
三、添加約束的時機【一定是在添加數據之前】
在這裏插入圖片描述
四、約束的添加分類
1、創建表時【圖片可以忽略不看,直接看代碼部分】
在這裏插入圖片描述
2、修改表時【圖片可以忽略不看,直接看代碼部分】
在這裏插入圖片描述
五、標識列【圖片可以忽略不看,直接看代碼部分】
在這裏插入圖片描述
六、注意點【圖片可以忽略不看,直接看代碼部分】
在這裏插入圖片描述
代碼如下:

#常見約束
/*
【含義:】一種限制,用於限制表中的數據,爲了保證表中數據的準確性和可靠性

【分類:】六大約束
	①NOT NULL:非空,用於保證該字段的值不能爲空(比如:姓名、學號)
	
	②DEFAULT:默認,用於保證字段有默認值(比如:性別)
	
	③PRIMARY KEY:主鍵,用於保證該字段的值具有唯一性,並且非空(比如:學號、員工編號)
	
	④UNIQUE:唯一,用於保證該字段的值具有唯一性,可以爲空(比如:座位號)
	
	⑤CHECK:檢查約束【mysql中不支持】(比如:年齡、性別)
	
	⑥FOREIGN KEY:外鍵,用於限制兩個表的關係,用於保證該字段的值必須來自於主表的關聯列的值。
	(在從表中添加外鍵約束,用於引用主表中某列的值)(比如:學生表的專業編號,員工表部門編號)
	
【添加約束的時機】(添加數據之前)
	1、創建表時 2、修改表時

【約束的添加分類】
	列級約束:6種約束語法上都支持,但外鍵約束沒有效果
	
	表級約束:除了 非空、默認 其它的都支持
*/
CREATE TABLE 表名(
	字段1 列類型 列級約束,
	字段2 列類型 列級約束,
	...
	字段n 列類型 列級約束,
	表級約束
);



#【創建表時添加約束】
#1、添加列級約束
/*
語法:直接在字段名和類型後面追加 約束類型 即可
只支持:默認、非空、主鍵、唯一
*/
CREATE TABLE stuinfo(
	id INT PRIMARY KEY,#主鍵
	stuName VARCHAR(20) NOT NULL,#非空
	gender CHAR(1) CHECK(gender='男' OR gender='女'),#檢查(mysql中不支持CHECK)
	seat INT UNIQUE,#唯一
	ange INT DEFAULT 18,#默認
	majorid INT REFERENCES major(id)#外鍵(對於列級約束,外鍵無效果)
);
CREATE TABLE major(
	id INT PRIMARY KEY,
	major_name VARCHAR(20)
);
#查看stuinfo中的所有索引(對於約束爲主鍵、外鍵、唯一的字段默認創建索引)
SHOW INDEX FROM stuinfo;
#2、添加表級約束
/*
語法:
	[constraint 約束名] 約束類型(字段名)
	通過show index from 表名,如果不寫約束名,默認是字段名,主鍵約束仍然是PRIMARY
*/
DROP TABLE IF EXISTS stuinfo;
CREATE TABLE IF NOT EXISTS stuinfo(
	id INT,
	stuname VARCHAR(20),
	gender CHAR(1),
	seat INT,
	age INT,
	majorid INT,
	CONSTRAINT pk PRIMARY KEY(id),#主鍵(對於主鍵來說,改名無效,默認是PRIMARY)
	CONSTRAINT uq UNIQUE(seat),#唯一鍵
	CONSTRAINT ck CHECK(gender='男' OR gender='女'),#檢查(mysql中不支持)
	CONSTRAINT fk FOREIGN KEY(majorid) REFERENCES major(id)#外鍵	
);
#通用的寫法
CREATE TABLE IF NOT EXISTS stuinfo(
	id INT PRIMARY KEY,
	stuname VARCHAR(20) NOT NULL,
	gender CHAR(1),
	seat INT UNIQUE,
	age INT DEFAULT 19,
	majorid INT,
	CONSTRAINT fk_stuinfo_major FOREIGN KEY(majorid) REFERENCES major(id)
	
);
DROP TABLE stuinfo
SHOW INDEX FROM stuinfo


/*【修改表時添加約束】
添加列級約束
alter table 表名 modify column 列名 列類型 新約束;

添加表級約束
alter table 表名 add [constraint 約束名] 約束類型(字段名) [外鍵引用][主表名(字段名)]
*/

#添加非空約束(列級約束)
ALTER TABLE stuinfo MODIFY COLUMN stuname VARCHAR(20) NOT NULL;
#添加默認約束(列級約束)
ALTER TABLE stuinfo MODIFY COLUMN age INT DEFAULT 18;
#添加外鍵約束(表級約束)
ALTER TABLE stuinfo ADD CONSTRAINT fk FOREIGN KEY(majorid) REFERENCES major(id);
#添加主鍵約束
#①列級
ALTER TABLE stuinfo MODIFY COLUMN id INT PRIMARY KEY;
#②表級
ALTER TABLE stuinfo ADD PRIMARY KEY(id);
#添加唯一約束
#①列級
ALTER TABLE stuinfo MODIFY COLUMN seat INT UNIQUE;
#②表級
ALTER TABLE stuinfo ADD UNIQUE(seat);

#【修改表時刪除約束】
#刪除默認約束
ALTER TABLE stuinfo MODIFY COLUMN age INT ;
#刪除非空約束
ALTER TABLE stuinfo MODIFY COLUMN stuname VARCHAR(20);
#刪除外鍵約束(創建表時候需要用constraint 指定約束名,否者刪除時候引用默認的約束名刪除失敗)
ALTER TABLE stuinfo DROP FOREIGN KEY fk;
#刪除主鍵約束
ALTER TABLE stuinfo DROP PRIMARY KEY;
#刪除唯一
ALTER TABLE stuinfo DROP INDEX uq;

#【標識列】
#修改表時添加標識列
ALTER TABLE stuinfo MODIFY COLUMN id INT AUTO_INCREMENT;
#修改表時刪除標識列
ALTER TABLE stuinfo MODIFY COLUMN id INT PRIMARY KEY;

04TCL(Transaction Control Language)事務控制語言【具體看代碼部分】

4-1概述

在這裏插入圖片描述

4-2案例

在這裏插入圖片描述

4-3存儲引擎

在這裏插入圖片描述

4-4事務的特點

在這裏插入圖片描述

4-5事務的創建

4-5-1隱式事務

在這裏插入圖片描述

4-5-2顯式事務【圖片可以忽略不看,直接看代碼部分】

在這裏插入圖片描述

4-6演示delete和truncate區別【圖片可以忽略不看,直接看代碼部分】

在這裏插入圖片描述

4-7設置保存點(類似於設置斷點)常搭配rollback使用【圖片可以忽略不看,直接看代碼部分】

在這裏插入圖片描述

4-8事務的併發問題【圖片可以忽略不看,直接看代碼部分】

在這裏插入圖片描述
在這裏插入圖片描述

4-9代碼展示

/*TCL(Transaction Control Language 事務控制語言)
一個或一組sq1語句組成一個執行單元,這個執行單元要麼全部執行,要麼全部不執行。

【事務】:事務由單獨單元的一個或多個SQL語句組成,在這個單元中,每個MySQL語句是相互依賴的,

整個單獨單元作爲一個不可分割的整體.
	如果單元中某條SQL語句一旦執行失敗或產生錯誤,整個單元將會回滾,所有受到影響的數據將返回到事物開始以前的狀態;
	如果單元中的所有SQL語句均執行成功,則事物被順利執行。
【案例】:轉賬
update 表 set A的餘額=1000 where name='A'
update 表 set B的餘額=500 where name='B'
A如果轉賬給B,如果A轉賬完畢後中途出錯,則會導致A的錢減少了但是B的錢卻沒有增加
*/

/*【存儲引擎】
1、概念:在mysq1中的數據用各種不同的技術存儲在文件(或內存)中
2、通過show engines; 來查看mysql支持的存儲引擎
3、在mysql中用的最多的存儲引擎有: innodb,myisam,memory等。
其中innodb支持事務,而myisam、memory等不支持事務
*/
SHOW ENGINES;
/*
【事務的特點】
事務的ACID屬性
A(Atomicity):原子性	【事務是一個不可分割的工作單位,事務中的操作要麼都發生,要麼都不發生】

C(Consistency):一致性	【事務必須使數據庫從一個致性狀態變換到另外一個致性狀態】(例如轉賬前後總金額不變)

I(Isolation):隔離性	【事務的隔離性是指一個事務的執行不能被其他事務干擾】,即一個
			事務內部的操作及使用的數據對併發的其他事務是隔離的,併發
			執行的各個事務之,間不能互相干擾.(同樣與隔離級別有關係)

D(Durability):持久性	【持久性是指一個事務一旦被提交,它對數據庫中數據的改變就是永久性的】,
			接下來的其他操作和數據庫故障不應該對其有任何影響
*/
/*
【事務的創建】
	【隱式事務】:事務沒有明顯的開啓和結束標記
		如insert、update、delete(默認開啓自動提交即:autocommit=ON)
		
	【顯式事務】:事務具有明顯的開啓和結束標記
		前提:必須設置自動提交功能爲禁用(set autocommit=0)
		【步驟】
		步驟1:開啓事務
			set autocommit = 0;
			start transaction;可選的,因爲設置autocommit禁用後,也默認開啓了事務
		步驟2:編寫事務中的sql語句
			語句1
			語句2
			...
		步驟3:結束事務
			commit;提交事務
			rollback;回滾事務
*/

SHOW VARIABLES LIKE 'autocommit';#Value=ON
#步驟一:開啓事務
SET autocommit = 0;
START TRANSACTION;
#步驟二:編寫事務中的sql語句
UPDATE author SET salary = 1500 WHERE `name` = 'A';
UPDATE author SET salary = 1000 WHERE `name` = 'B';
#步驟三:結束事務
ROLLBACK;
SELECT * FROM author;
#【演示truncate、delete】
#演示truncate不可以回滾【數據已經被刪除】
SET autocommit=0;
START TRANSACTION;
TRUNCATE TABLE author;
ROLLBACK;
#演示delete可以回滾【數據依舊存在】
SET autocommit=0;
START TRANSACTION;
DELETE FROM author;
ROLLBACK;
#【設置保存點】格式savepoint 節點名(類似於設置斷點)
SET autocommit=0;
START TRANSACTION;
DELETE FROM author WHERE id = 100;
DELETE FROM author WHERE id = 101;
SAVEPOINT a;#設置保存點
DELETE FROM author WHERE id IN(102,103,104);
ROLLBACK TO a;#回滾到保存點
SELECT * FROM author;

05視圖【具體看代碼部分】

5-1概述

在這裏插入圖片描述

5-2視圖的好處

在這裏插入圖片描述

5-3案例

在這裏插入圖片描述

5-4視圖的創建

5-4-1語法

在這裏插入圖片描述

5-4-2案例

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

5-5視圖的修改

在這裏插入圖片描述

5-6視圖的刪除

在這裏插入圖片描述

5-7查看視圖

在這裏插入圖片描述

5-8視圖的更新【不常用】

在這裏插入圖片描述

5-9視圖與表的對比

在這裏插入圖片描述

5-10代碼展示

#視圖
/*
①虛擬表,和普通的表一樣使用

②mysql5.1版本出現的新特性

③行和列的數據來自定義視圖的查詢中使用的表,並且是在使用視圖時動態生成的,只保存了sq|邏輯,不
保存查詢結果

【應用場景】
	①多個地方用到同樣的查詢結果
	②該查詢結果使用的sql語句較複雜
*/
#案例:查詢姓張的學生名和專業名
CREATE VIEW v1
AS
SELECT stuname,majorname
FROM stuinfo s
INNER JOIN major m ON s.majorid=m.id;
#利用視圖實現案例
SELECT * FROM v1 WHERE stuname LIKE '張%';
#【視圖的創建】
/*
語法:
	create view 視圖名
	AS
	查詢語句;(一般是比較複雜的查詢語句)
*/
#【案例1】:查詢姓名中包含a字符的員工名、部門名和工種信息
#①創建
CREATE VIEW myv1
AS
SELECT last_name,department_name,job_title
FROM employees e
INNER JOIN departments d ON e.department_id=d.department_id
INNER JOIN jobs j ON e.job_id=j.job_id;
#②使用
SELECT last_name,department_name,job_title
FROM myv1
WHERE last_name LIKE '%a%';
#【案例2】:查詢各部門的平均工資級別
#創建平均工資視圖
CREATE VIEW myv2
AS
SELECT AVG(salary) ag,department_id
FROM employees
GROUP BY department_id;
#使用
SELECT	ag,grade_level
FROM myv2
INNER JOIN job_grades j 
ON myv2.`ag` BETWEEN j.`lowest_sal` AND j.`highest_sal`;
#【案例3】:查詢平均工資最低的部門信息
SELECT * FROM myv2
ORDER BY myv2.`ag`
LIMIT 1;
#【視圖的修改】
/*
方式一:
	create or replace view 視圖名
	as
	查詢語句;
*/
CREATE VIEW testv1
AS
SELECT * FROM employees;

CREATE OR REPLACE VIEW testv1
AS
SELECT last_name FROM employees;

SELECT * FROM testv1;
/*
方式二:
	alter view 視圖名
	as
	查詢語句;
*/

ALTER VIEW testv1
AS
SELECT * FROM employees;
#【視圖的刪除】語法:drop view 視圖名1,,視圖名2...,視圖名n;
DROP VIEW myv1,myv2,testv1;

06變量【具體看代碼部分】

6-1系統變量(按照作用範圍分)

6-1-1全局變量

在這裏插入圖片描述

6-1-2會話變量

在這裏插入圖片描述

6-2自定義變量(按照作用範圍分)

變量是用戶自定義的,不是由系統提供的

6-2-1使用步驟

在這裏插入圖片描述

6-2-2用戶變量

在這裏插入圖片描述

6-2-3局部變量

在這裏插入圖片描述

6-2-4用戶變量和局部變量對比

在這裏插入圖片描述

6-3代碼展示

/*
變量:
系統變量:(按照作用範圍不同)
	全局變量
	會話變量
自定義變量:(按照作用範圍不同)
	用戶變量
	局部變量
*/
#【系統變量】
/*
注意:如果是全局級別,則需要加GLOBAL,如果是會話級別,則需要加SESSION,如果不寫,則默認SESSION

說明:變量由系統提供,不是用戶定義,屬於服務器層面

使用的語法:
1、查看所有的系統變量:(如果不聲明global或session,默認是session)
show global|[session] variables;

2、查看滿足條件的部分系統變量:(如下)
show global|[session] variables like '%char%';

3、查看指定的某個系統變量的值
select @@global|[session].系統變量名

4、爲某個系統變量賦值
方式一:
	set @@global|[session].系統變量名 = 值;
方式二:
	set global|[session] 系統變量名 = 值;
*/
#【全局變量】
#查看所有的全局變量
SHOW GLOBAL VARIABLES;
#查看部分的全局變量
SHOW GLOBAL VARIABLES LIKE '%char%';
#查看指定的全局變量的值
SELECT @@global.autocommit;
#爲某個指定的全局變量賦值
SET @@global.autocommit = 0;
#【會話變量】
#作用域:僅僅針對於當前會話(連接)有效
#查看所有的會話變量
SHOW VARIABLES;
SHOW SESSION VARIABLES;
#查看部分的會話變量
SHOW VARIABLES LIKE '%char%';
SHOW SESSION VARIABLES LIKE '%char%';
#查看指定的會話變量
SELECT @@tx_isolation;
SELECT @@session.tx_isolation;
#爲某個會話變量賦值
SET @@session.tx_isolation = 'read-committed';
SET SESSION tx_isolation = 'read-committed';
#【自定義變量】
/*
說明:變量是用戶自定義的,不是由系統提供的
使用步驟:
	聲明
	賦值
	使用(查看、比較、運算等)
*/
#【用戶變量】作用域:針對於當前會話(連接)有效,同於會話變量的作用域
#應用在任何地方,也就是begin end裏面或begin end外面
/*
1、聲明並初始化:(三種方式)
	set @用戶變量名=值
	set @用戶變量名:=值
	select @用戶變量名:=值
2、賦值(更新用戶變量的值)
方式一:
	set @用戶變量名=值
	set @用戶變量名:=值
	select @用戶變量名:=值
	
方式二:通過select into
	select 字段 into @變量名
	from 表;
3、使用(查看用戶變量的值)
	select @用戶變量名

*/
#【局部變量】
#作用域:僅僅在定義它的begin end中有效
#應用在begin end中的第一句話
/*
1、聲明:
	declare 變量名 類型;
	declare 變量名 類型 default 值;
2、賦值
方式一:
	set 局部變量名=值
	set 局部變量名:=值
	select @局部變量名:=值
	
方式二:通過select into
	select 字段 into 局部變量名
	from 表;
3、使用
select 局部變量名;
*/
/*
用戶變量 vs 局部變量
		作用域		定義和使用的位置 		語法
用戶變量	當前會話	會話中的任何地方		必須加@符號,不用限定類型
局部變量	begin end中	在begin end中,且爲第一句話	一般不用加@符號,需要限定類型
*/

07存儲過程【具體看代碼部分】

7-1概述

在這裏插入圖片描述

7-2注意點

在這裏插入圖片描述

7-3調用語法,具體看代碼部分

call 存儲過程名(實參列表);
一、空參列表
二、創建帶in模式參數的存儲過程
1、一個in模式參數
2、多個in模式參數
三、創建帶out模式參數的存儲過程
1、一個out模式參數
2、多個out模式參數
四、創建帶inout模式參數的存儲過程

7-4存儲過程的刪除

在這裏插入圖片描述

7-5查看存儲過程的信息

在這裏插入圖片描述

7-6代碼展示

#存儲過程和函數
/*
存儲過程和函數:類似於java中的方法
方法的好處:
	1、提高了代碼的重用性
	2、簡化操作
*/
/*
存儲過程:
含義:一組預先編譯好的SQL語句的集合,理解成批處理語句
好處:
	1、提高了代碼的重用性
	2、簡化操作
	3、減少了編譯次數,並減少了和數據庫服務器的連接次數,提高了效率
*/
/*創建語法:
create procedure 存儲過程名(參數列表)
begin
	存儲過程體(一組合法的sql語句)
end
【注意】參數列表包含三部分
	【1】參數模式 參數名 參數類型
		【舉例】
		in stuname varchar(20)
	【2】	【參數模式】
		in:該參數可以作爲輸入,也就是該參數需要調用方傳入值
		out:該參數可以作爲輸出,也就是該參數可以作爲返回值
		inout:該參數既可以作爲輸入又可以作爲輸出.也就是該參數既需要傳入值,又可以返回值
	【3】
	     如果存儲過程體僅僅只有一句話,BEGIN END可以省略。
	     存儲過程體中的每條sQL語句的結尾要求必須加分號。
	     存儲過程的結尾可以使用DELIMITER重新設置。
	     語法:
		delimiter 結束標記
【調用語法】
	call 存儲過程名(實參列表);
*/
#【空參列表】
#案例:向t1中插入3條記錄
DELIMITER $
CREATE PROCEDURE p1()
BEGIN
	INSERT INTO t1(NAME,salary) VALUES('a',100),
	('b',100),('c',100);
END $
#調用
CALL p1()$
#【創建帶in模式參數的存儲過程】
#案例:創建存儲過程實現根據女神名,查詢對應的男神信息
CREATE PROCEDURE p2(IN beautyName VARCHAR(20))
BEGIN
	SELECT bo.*
	FROM boys bo
	INNER JOIN beauty b ON bo.id = b.boyfriend_id
	WHERE b.name = beautyName;
END $
#調用
CALL p2('王昭君')$
#案例2:創建存儲過程實現,用戶是否登錄成功
CREATE PROCEDURE p3(IN username VARCHAR(20),IN `password` VARCHAR(20))
BEGIN
	DECLARE result INT DEFAULT 0;#聲明並初始化
	SELECT COUNT(*) INTO result#賦值
	FROM admin
	WHERE admin.username = username
	AND
	admin.password = `password`;
	
	SELECT IF(result>0,'登陸成功','登陸失敗');#使用
END $
#調用
CALL p3('admin','password')$
#【創建帶out模式參數的存儲過程】
#案例1:根據女神名,返回對應的男神名
CREATE PROCEDURE p4(IN beautyName VARCHAR(20),OUT boyName VARCHAR(20))
BEGIN
	SELECT bo.boyName INTO boyName
	FROM boys bo
	INNER JOIN beauty b ON bo.id = b.boyfriend_id
	WHERE b.name = beautyName;
END $
#調用(可以在調用前聲明一個用戶變量:set @bName$)
CALL p4('王昭君',@bName)$

#案例2:根據女神名,返回對應的男神名和男神魅力值
CREATE PROCEDURE p5(IN beautyName VARCHAR(20),OUT boyName VARCHAR(20),OUT userCP INT)
BEGIN
	SELECT bo.boyName,bo.userCP INTO boyName,userCP
	FROM boys bo
	INNER JOIN beauty b ON bo.id = b.boyfriend_id
	WHERE b.name = beautyName;
END $
#調用
CALL p5('王昭君',@bName,@usercp)$
#【創建帶inout模式參數的存儲過程】
CREATE PROCEDURE p6(INOUT m INT,INOUT n INT)
BEGIN
	SET m=m*2;
	SET n=n*2;
END $
#調用
SET @a = 10$
SET @b = 20$
CALL p6(@a,@b)$
SELECT @a,@b$

08函數【具體看代碼部分】

8-1含義

一組預先編譯好的SQL語句的集合,理解成批處理語句

8-2好處

在這裏插入圖片描述

8-3創建語法

在這裏插入圖片描述

8-4注意點

在這裏插入圖片描述

8-5存儲過程 vs 函數

在這裏插入圖片描述

8-6調用語法

在這裏插入圖片描述

8-7查看函數

在這裏插入圖片描述

8-8刪除函數

在這裏插入圖片描述

8-9代碼展示

/*
函數(同存儲過程的定義一樣):
含義:一組預先編譯好的SQL語句的集合,理解成批處理語句
好處:
	1、提高了代碼的重用性
	2、簡化操作
	3、減少了編譯次數,並減少了和數據庫服務器的連接次數,提高了效率
區別:
存儲過程:可以有0個返回,也可以有多個返回,適合做批量插入、批量更新
函數:有且僅有1個返回,適合做處理數據後返回一個結果
*/
/*
【創建語法】:
create function 函數名(參數列表) returns 返回類型
begin
	函數體
end

【注意】:
	1.參數列表包含兩部分:	參數名、參數類型
	2.函數體:肯定會有return語句,如果沒有會報錯
	如果return語句沒有放在函數體的最後也不報錯,但不建議

	return 值;
	3.函數體中僅有一句話,則可以省略begin end
	4.使用delimiter語句設置結束標記
【調用語法】
select 函數名(參數列表);
*/
#1、【無參有返回值】
#案例:返回公司員工個數
DELIMITER $
CREATE FUNCTION fun1() RETURNS INT
BEGIN
	DECLARE c INT DEFAULT 0;#定義局部變量
	SELECT COUNT(*) INTO c#爲局部變量賦值
	FROM employees;
	RETURN c;
END $
#調用
SELECT fun1()$
#【有參,有返回】
#案例:根據員工名,返回其工資
CREATE FUNCTION fun2(e_name VARCHAR(20)) RETURNS DOUBLE
BEGIN
	SET @salary = 0;#定義用戶變量
	SELECT employees.salary INTO @salary
	FROM employees
	WHERE last_name = e_name;
	RETURN @salary;
END $
#調用
SELECT fun2('張三')$
#【查看函數】 show create function 函數名;
#【刪除函數】 drop function 函數名;
CREATE FUNCTION fun2(m INT,n INT) RETURNS INT
BEGIN
 RETURN m+n;
END $

09流程控制【具體看代碼部分】

9-1順序結構

程序從上往下依次執行

9-2分支結構

9-2-1if函數

在這裏插入圖片描述

9-2-2case結構

一、作爲表達式
在這裏插入圖片描述
二、作爲獨立語句
在這裏插入圖片描述
三、案例在這裏插入圖片描述

9-2-3if結構

在這裏插入圖片描述

9-3循環結構

在這裏插入圖片描述
案例:
在這裏插入圖片描述
在這裏插入圖片描述

9-4經典案例

在這裏插入圖片描述

9-5代碼展示

/*
流程控制結構
	順序結構:程序從上往下依次執行
	分支結構:程序從兩條或多條路徑中選擇一條去執行
	循環結構:程序在滿足一定條件的基礎上,重複執行一段代碼
*/
/*
【分支結構】:
if函數:
	功能:實現簡單的雙分支
	語法:select if(表達式1,表達式2,表達式3)
	執行順序:如果表達式1成立,那麼返回表達式2的值,反之返回表達式3的值
	應用:任何位置

case結構:
	情況1:類似於java中的switch語句,一般用於實現等值判斷
	語法:
		case 表達式|變量|字段
		when 要判斷的值 then 返回的值1或語句1;
		when 要判斷的值 then 返回的值2或語句2;
		...
		else 要返回的值n或語句n;
		end case;
		
	情況2:類似於java中的多重IF語句, 一般用於實現區間判斷
	語法:
		case
		when 要判斷的條件1 then 返回值1或語句1;
		when 要判斷的條件2 then 返回值1或語句2;
		...
		else 要返回值n或語句n;
		end case;

if結構:
	功能:實現多重分支
	語法:if 條件1 then 語句1;
	      elseif 條件2 then 語句2;
	      ...
	      [else 語句n;]
	      end if;
	應用:
	      只能在begin end中
*/
/*
案例:
創建存儲過程,根據傳入的成績,來顯示等級,比如傳入的成績: 90-100顯示A,80-90顯示B,60-80顯示c,否則D
*/
CREATE PROCEDURE p1(IN score FLOAT)
BEGIN
	CASE
	WHEN score BETWEEN 90 AND 100 THEN SELECT 'a';
	WHEN score>80 THEN SELECT 'b';
	WHEN score>60 THEN SELECT 'c';
	ELSE SELECT 'd';
	END CASE;
END $
CALL p1(90)$
#創建函數,根據傳入的成績,來顯示等級,比如傳入的成績: 90-100返回A,80-90返回B,60-80返回c,否則返回D
CREATE FUNCTION test_if(score FLOAT) RETURNS CHAR
BEGIN
	IF score BETWEEN 90 AND 100 THEN RETURN 'a';
	ELSEIF score>80 THEN RETURN 'b';
	ELSEIF score>60 THEN RETURN 'c';
	ELSE RETURN 'd';
	END IF;
END $
/*
【循環結構】
分類:while、loop、repeat
循環控制:
	iterate 類似於continue繼續,結束本次循環,繼續下一次
	leave   類似於break,跳出,結束當前所在的循環
	【語法】:
	1、while
		[標籤]:while 循環條件 do
			循環體;
		       end while [標籤];
		       
	2、loop
		[標籤]:loop
			循環體;
			end loop [標籤];
	可以用來模擬簡單的死循環
	
	3、repeat
		[標籤]:repeat
			循環體;
			until 結束循環的條件
			end repeat [標籤];
*/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章