MySQL基础-学习笔记

MySQL基础

一、DQL语言的学习

1.基础查询

/*
语法:
select 查询列表 from 表名

特点:
1-查询的结果集是一个虚拟表
2-select类似于System.out.printIn(打印内容)
	select后面跟的查询列表,可以有很多个部分组成,中间用逗号隔开
	例如:select 字段1,字段2,字段3 from 表
	System.out.printIn()的打印内容只有一个
3-执行顺序
select first_name from employees222;
	a.  from子句
	b.  select子句
4-查询列表:

*/

# 一、查询常量
SELECT 100;

# 二、查询表达式
SELECT 100%3;

# 三、查询单个字段
SELECT `last_name` FROM `employees` ;

# 四、查询多个字段,Fn+F12快速对齐格式
SELECT 
  `last_name`,
  `email`,
  `employee_id` 
FROM
  `employees` ;

# 五、查询所有字段
SELECT * FROM `employees`;

# 六、调用函数、获取返回值
# 查询当前数据库
SELECT DATABASE();
# 查询版本
SELECT VERSION();
SELECT USER();

# 七、起别名
# 方式一:使用as关键字
SELECT USER() AS 用户名;
SELECT USER() AS '用户名';
SELECT USER() AS "用户名";

#方式二:使用空格
SELECT USER()  用户名;
SELECT USER()  '用户名';
SELECT USER()  "用户名";

# 八、
# 需求:查询first_name 和last_name 拼接的全名,最终起别名为:姓  名

# 方案一
SELECT first_name+last_name AS "姓  名"
FROM `employees`;

/*
Java中+的作用:
1.加法运算
2.拼接符
	至少有一方为字符串

MySQL中+的作用:
	加法运算
*/

# 方案二:使用concat拼接函数
SELECT CONCAT (first_name,last_name) AS "姓  名"
FROM `employees`;


# 九、distinct的使用
# 需求:查询员工涉及到的部门
SELECT DISTINCT `department_id` FROM `employees`;

# 十、查看表的结构
DESC employees;
SHOW COLUMNS FROM employees;

基础查询案例

# 1.下面的语句是否可以执行成功?
SELECT last_name , job_id , salary AS sal
FROM employees;
# 可以,换行没问题

# 2.下面的语句是否可以执行成功?
SELECT * FROM employees;
# 可以,意思是查询所有字段

# 3.找出下面语句的错误
SELECT employee_id , last_name,
salsry * 12 "ANNUAL SALARY"
FROM employees;
# 题中所有符号都应该用英文

# 4.显示表departments的结构,并查询全部数据
DESC departments;
SHOW COLUMNS FROM departments;
SELECT * FROM departments;

# 5.显示出表employees中全部的job_id(不能重复)
SELECT DISTINCT job_id FROM employees;
# distinct 表示不能重复

# 6.显示出表employees的全部列,各个列之间用逗号连接,列头显示为OUT_PUT
SELECT CONCAT(employee_id , ',' ,first_name , ',' , last_name , ',' ,salary , ',' , 
IFNULL(commission_pct , '')) AS "OUT_PUT"  FROM employees;
# concat表示拼接,但需要注意的是,拼接值中有NULL时,整体为NULL
# 可以借用 ifnull:如果不是null,则返回参数1,如果是null,则返回参数2

SELECT commission_pct , IFNULL(commission_pct , '空') FROM employees;

2.条件查询

/*
语法:
select 查询列表
from 表名
where 筛选条件; 

执行顺序:
1.from 子句
2.where 子句
3.select 子句

举例:select last_name , first_name from employees where salary>20000;

特点:
1.按关系表达式筛选
	关系运算符:< > >=  <=  <>
2.按逻辑表达式筛选
	逻辑运算符:and(&&) , or(||) , not(!)
3.模糊查询
	like ,  in  , between and  , is null

*/

# 一、按关系表达式筛选
# 案例1:查询部门编号不是100的员工信息
SELECT * 
FROM employees
WHERE department_id <> 100;

#案例2:工资小于15000的姓名还有工资
SELECT last_name , salary 
FROM employees
WHERE salary < 15000;

# 二、按逻辑表达式筛选
# 案例1:查询部门编号不是 50-100 之间的员工的姓名、部门编号、邮箱
# 方式1
SELECT last_name , department_id , email
FROM employees
WHERE department_id<50 OR department_id>100;
# 方式2
SELECT last_name , department_id , email
FROM employees
WHERE NOT(department_id>=50 AND department_id<=100);

# 案例2:查询奖金率>0.03 或者 员工编号在66-110之间的员工信息
SELECT * 
FROM employees
WHERE commission_pct>0.03 OR (employee_id>=60 AND employee_id<=110);

# 三、模糊查询
# 1. like
/*
功能:一般和通配符搭配使用,对字符型数据进行部分匹配查询
常见通配符:
_  任意单个字符
%  任意多个字符
*/

# 案例1:查询姓名中包含字符a的员工信息
SELECT *
FROM employees
WHERE last_name LIKE '%a%';

# 案例2:查询姓名中最后一个字符为e的员工信息
SELECT *
FROM employees
WHERE last_name LIKE '%e';

# 案例3:查询姓名中第一个字符为e的员工信息
SELECT *
FROM employees
WHERE last_name LIKE 'e%';

# 案例4:查询姓名中第3个字符为x的员工信息
SELECT *
FROM employees
WHERE last_name LIKE '__x%';

# 案例5:查询姓名中第二个字符为_的员工信息
SELECT *
FROM employees
WHERE last_name LIKE '_\_%';
# \ :转义字符
# 也可以自己设置转义字符
SELECT *
FROM employees
WHERE last_name LIKE '_$_%' ESCAPE '$';

# 2. in 
/*
功能:查询某字段的值是否属于指定的列表之内
a in(常量0,常量1,常量2,常量3,...)
a not in(常量0,常量1,常量2,常量3,...)
*/

# 案例1 :查询部门编号是30,50,90的员工姓名,部门编号
SELECT last_name , department_id
FROM employees
WHERE department_id IN(30,50,90);

# 案例2:查询工种编号不是SH_CLERK或IT_PROG的员工信息
SELECT *
FROM employees
WHERE job_id NOT IN ('SH_CLERK','IT_PROG');

# 3. between and 
/*
功能:判断某个字段的值是否介于xx之间
*/

# 案例1:查询部门编号是30-90之间的部门编号、员工姓名
SELECT department_id ,last_name
FROM employees
WHERE department_id BETWEEN 30 AND 90 ;

# 案例2:查询年薪不是100000-200000之间的员工姓名、工资、年薪
SELECT last_name , salary , salary*12*(1+IFNULL(commission_pct, 0)) 年薪
FROM employees
WHERE salary*12*(1+IFNULL(commission_pct, 0)) <100000 OR 
salary*12*(1+IFNULL(commission_pct, 0)) > 200000;

SELECT last_name , salary , salary*12*(1+IFNULL(commission_pct, 0)) 年薪
FROM employees
WHERE salary*12*(1+IFNULL(commission_pct, 0)) NOT BETWEEN 100000 AND 200000;

# 4. is null  /  is not null
# 案例1 :查询没有奖金的员工信息
SELECT *
FROM employees
WHERE commission_pct IS NULL;

#案例2 :查询有奖金的员工信息
SELECT*
FROM employees
WHERE commission_pct IS NOT NULL ;

# <=> : 安全等于,既能判断普通内容,又能判断null值

# 课堂测试

# 1.查询工资大于12000的员工姓名和工资
SELECT last_name , salary
FROM employees
WHERE salary > 12000;

# 2.查询员工工号为176的员工的姓名和部门号和年薪
SELECT employee_id , last_name , department_id,salary*12*(1+IFNULL(commission_pct,0))年薪
FROM employees
WHERE employee_id=176;

# 3.选择工资不在5000到12000的员工的姓名和工资
SELECT last_name , salary
FROM employees
WHERE salary NOT BETWEEN 5000 AND 12000;

# 4.选择在20 或50 号部门工作的员工姓名和部门号
SELECT last_name , department_id
FROM employees
WHERE department_id IN(20 , 50);

# 5.选择公司中没有管理者的员工姓名及job_id
SELECT last_name , job_id 
FROM employees
WHERE manager_id IS NULL ; 

# 6.选择公司中有奖金的员工姓名,工资和奖金级别
SELECT last_name , salary , commission_pct
FROM employees
WHERE commission_pct IS NOT NULL ;

# 7.选择员工姓名的第三个字母是a的员工姓名
SELECT last_name
FROM employees
WHERE last_name LIKE '__a%';

# 8.选择姓名中有a和e的员工姓名
SELECT last_name
FROM employees
WHERE last_name LIKE '%a%' AND last_name LIKE '%e%';

# 9.显示出表employees中first name 以 e 结尾的员工信息
SELECT *
FROM employees
WHERE first_name LIKE '%e';

# 10.显示出表中部门编号在80-100之间的姓名、职位
SELECT last_name,job_id
FROM employees
WHERE department_id BETWEEN 80 AND 100;

# 11.显示表中manager_id 是100,101,110的员工的姓名职位
SELECT last_name , job_id
FROM employees
WHERE manager_id IN (100 , 101 , 110);

3.排序查询

/*
语法:
select 查询列表
from 表明
where 筛选条件
order by 排序列表

执行顺序:
1.from 子句
2.where 子句
3.select 子句
4.order by 子句

举例:
select last_name , salary
from employees
where salary>10000
order by salary ;

特点:
1.排序列表可以是单个字段、多个字段、表达式、函数、列数、以及以上的组合
2.升序,通过asc,默认
  降序,通过deac
*/

# 一、按单个字段排序
# 案例1:员工编号大于120的工资降序
SELECT * FROM employees WHERE employee_id>120 ORDER BY salary DESC;

# 二、按表达式排序
# 案例1:对有奖金的员工,按年薪降序
SELECT * , salary*12*(1+IFNULL(commission_pct,0))年薪
FROM employees
WHERE commission_pct IS NOT NULL
ORDER BY  salary*12*(1+IFNULL(commission_pct,0)) DESC;

# 三、按别名排序
# 案例1:对有奖金的员工,按年薪降序
SELECT * , salary*12*(1+IFNULL(commission_pct,0))年薪
FROM employees
WHERE commission_pct IS NOT NULL
ORDER BY 年薪 DESC;

# 四、按函数的结果排序
# 案例1:根据姓名的字数长度进行升序
SELECT LENGTH(last_name),last_name
FROM employees
ORDER BY LENGTH(last_name);

# 五、按多个字段进行排序
# 案例1:查询员工的姓名、工资、部门编号、先按工资升序、再按部门编号降序
SELECT last_name , salary , department_id
FROM employees
ORDER BY salary ASC , department_id DESC ;

# 六、按列数排序
SELECT * FROM employees 
ORDER BY 2;

# 作业:
USE myemployees
# 1.查询员工的姓名和部门号和年薪,按年薪降序
SELECT last_name , department_id , salary*12*(1+IFNULL(commission_pct , 0))年薪
FROM employees
ORDER BY 年薪 DESC;

# 2.选择工资不在8000到17000的员工姓名和工资,按工资降序
SELECT last_name , salary 
FROM employees 
WHERE salary NOT BETWEEN 8000 AND 17000
ORDER BY salary DESC;

# 3.查询邮箱中包含e的员工信息,并先按邮箱的字节数降序,在按部门编号升序
SELECT *
FROM employees
WHERE email LIKE '%e%'
ORDER BY LENGTH(email) DESC , department_id;

4.常见函数

#一、字符函数
1、CONCAT 拼接字符

SELECT CONCAT('hello,',first_name,last_name)  备注 FROM employees;

2、LENGTH 获取字节长度

SELECT LENGTH('hello,郭襄');

3、CHAR_LENGTH 获取字符个数
SELECT CHAR_LENGTH('hello,郭襄');

4、SUBSTRING 截取子串
/*
注意:起始索引从1开始!!!
substr(str,起始索引,截取的字符长度)
substr(str,起始索引)
*/
SELECT SUBSTR('张三丰爱上了郭襄',1,3);
SELECT SUBSTR('张三丰爱上了郭襄',7);

5、INSTR获取字符第一次出现的索引

SELECT INSTR('三打白骨精aaa白骨精bb白骨精','白骨精');

6、TRIM去前后指定的字符,默认是去空格


SELECT TRIM(' 虚  竹    ')  AS a;
SELECT TRIM('x' FROM 'xxxxxx虚xxx竹xxxxxxxxxxxxxxxxxx')  AS a;

7、LPAD/RPAD  左填充/右填充
SELECT LPAD('木婉清',10,'a');
SELECT RPAD('木婉清',10,'a');

8、UPPER/LOWER  变大写/变小写

#案例:查询员工表的姓名,要求格式:姓首字符大写,其他字符小写,名所有字符大写,且姓和名之间用_分割,最后起别名“OUTPUT”


SELECT UPPER(SUBSTR(first_name,1,1)),first_name FROM employees;
SELECT LOWER(SUBSTR(first_name,2)),first_name FROM employees;
SELECT UPPER(last_name) FROM employees;

SELECT CONCAT(UPPER(SUBSTR(first_name,1,1)),LOWER(SUBSTR(first_name,2)),'_',UPPER(last_name)) "OUTPUT"
FROM employees;

9、STRCMP 比较两个字符大小

SELECT STRCMP('aec','aec');


10、LEFT/RIGHT  截取子串
SELECT LEFT('鸠摩智',1);
SELECT RIGHT('鸠摩智',1);
#二、数学函数
1、ABS 绝对值
SELECT ABS(-2.4);
2、CEIL 向上取整  返回>=该参数的最小整数
SELECT CEIL(-1.09);
SELECT CEIL(0.09);
SELECT CEIL(1.00);

3、FLOOR 向下取整,返回<=该参数的最大整数
SELECT FLOOR(-1.09);
SELECT FLOOR(0.09);
SELECT FLOOR(1.00);

4、ROUND 四舍五入
SELECT ROUND(1.8712345);
SELECT ROUND(1.8712345,2);

5、TRUNCATE 截断

SELECT TRUNCATE(1.8712345,1);

6、MOD 取余

SELECT MOD(-10,3);
a%b = a-(INT)a/b*b
-10%3 = -10 - (-10)/3*3   = -1

SELECT -10%3;
SELECT 10%3;
SELECT -10%-3;
SELECT 10%-3;
#三、日期函数
1、NOW
SELECT NOW();

2、CURDATE

SELECT CURDATE();

3、CURTIME
SELECT CURTIME();


4、DATEDIFF
SELECT DATEDIFF('1998-7-16','2019-7-13');

5、DATE_FORMAT

SELECT DATE_FORMAT('1998-7-16','%Y年%M月%d日 %H小时%i分钟%s秒') 出生日期;



SELECT DATE_FORMAT(hiredate,'%Y年%M月%d日 %H小时%i分钟%s秒')入职日期 
FROM employees;



6、STR_TO_DATE 按指定格式解析字符串为日期类型
SELECT * FROM employees
WHERE hiredate<STR_TO_DATE('3/15 1998','%m/%d %Y');
#四、流程控制函数
1、IF函数

SELECT IF(100>9,'好','坏');


#需求:如果有奖金,则显示最终奖金,如果没有,则显示0
SELECT IF(commission_pct IS NULL,0,salary*12*commission_pct)  奖金,commission_pct
FROM employees;



2、CASE函数

①情况1 :类似于switch语句,可以实现等值判断
CASE 表达式
WHEN 值1 THEN 结果1
WHEN 值2 THEN 结果2
...
ELSE 结果n
END


案例:
部门编号是30,工资显示为2倍
部门编号是50,工资显示为3倍
部门编号是60,工资显示为4倍
否则不变

显示 部门编号,新工资,旧工资

SELECT department_id,salary,
CASE department_id
WHEN 30 THEN salary*2
WHEN 50 THEN salary*3
WHEN 60 THEN salary*4
ELSE salary
END  newSalary
FROM employees;


②情况2:类似于多重IF语句,实现区间判断
CASE 
WHEN 条件1 THEN 结果1
WHEN 条件2 THEN 结果2
...

ELSE 结果n

END

案例:如果工资>20000,显示级别A
      工资>15000,显示级别B
      工资>10000,显示级别C
      否则,显示D
      
 SELECT salary,
 CASE 
 WHEN salary>20000 THEN 'A'
 WHEN salary>15000 THEN 'B'
 WHEN salary>10000 THEN 'C'
 ELSE 'D'
 END
 AS  a
 FROM employees;  

5.分组函数

/*
用于实现将一组数据进行统计计算,最终得到一个值,又称聚合函数和统计函数
分组函数清单:
sum(字段名):求和
avg():求平均
max():
min():
count():计算非空字段的个数,也就是他本身就去掉了空值

*/

案例1:查询员工的信息表中,工资和、工资平均、最低和最高

SELECT SUM(salary),AVG(salary),MIN(salary),MAX(salary),COUNT(salary) FROM employees;

案例2:添加筛选条件

#查询表中的记录数
SELECT COUNT(employee_id) FROM employees;

#查询表中有佣金的人数;
SELECT COUNT(salary) FROM employees;

#查询月薪大于2500的人数
SELECT COUNT(salary) FROM employees WHERE salary>2500;

#查询有领导的人数
SELECT COUNT(manager_id) FROM employees;

count补充

SELECT COUNT(*) FROM employees;
SELECT COUNT(1) FROM employees WHERE department_id=30;

2**.搭配distinct实现去重的统计**

需求:查询有员工的部门个数(逻辑是去掉部门的重复项)

SELECT COUNT(DISTINCT department_id) FROM employees;

思考:每个部门的总工资、平均工资?使用group by分组查询

SELECT department_id,SUM(salary),AVG(salary) FROM employees
GROUP BY department_id;

6.分组查询

进阶6:分组查询

/*
语法:
select 查询列表
from 表明
where 筛选
group by 分组列表
HAVING 分组后筛选
ORDER BY 排序;

执行顺序:

1. from 表明
2. where 筛选
3. group by 分组列表
4. HAVING 分组后筛选
5. select 查询列表
6. ORDER BY 排序;

特点:
1.查询的列表是分组字段
2.分组筛选的分类
              基于那个表     使用的关键词       位置
分组前筛选:    原始表         where           group by 的前面     
分组后筛选:    分组后的表      having         group by 的后面  

*/
1.简单分组
案例1:查询每个工种的员工平均工资

SELECT job_id,AVG(salary) FROM employees GROUP BY job_id;

案例2:查询么个领导的手下人数

SELECT manager_id,COUNT(*) FROM employees GROUP BY manager_id;
2.可以实现分组前的筛选
案例1:邮箱中包含a的每个部门的最高的工资

SELECT MAX(salary) FROM employees WHERE email LIKE '%a%' GROUP BY department_id;

案例2: 查询每个领导手下有奖金的员工的平均工资

SELECT AVG(salary),manager_id FROM employees 
WHERE commission_pct IS NOT NULL 
GROUP BY manager_id;  
3.可以实现分组后的筛选
案例1:查询那个部门的员工个数大于5

SELECT COUNT(*),department_id FROM employees 
GROUP BY department_id;

案例2:每个工种有奖金的员工的最高工资>12000的工种编号和最高工资

SELECT job_id,MAX(salary) FROM employees 
WHERE commission_pct IS NOT NULL 
GROUP BY job_id
HAVING MAX(salary)>12000;        

#案例3:领导编号>102的每个领导手下的最低工资大于5000的领导编号和最低工资
SELECT manager_id , MIN(salary) FROM employees
WHERE manager_id>102
GROUP BY manager_id
HAVING MIN(salary) > 5000;
4.可以实现排序
案例:查询没有奖金的员工的最高工资>6000的工种编号和最高工资,按最高工资升序

分析1 :按工种分组,查询有奖金的员工的最高工资

SELECT MAX(salary) 最高工资,job_id
FROM employees
WHERE commission_pct IS NULL
GROUP BY job_id;

分析2 : 筛选刚刚结果

SELECT MAX(salary) 最高工资 , job_id
FROM employees
WHERE commission_pct IS NULL
GROUP BY job_id
HAVING MAX(salary)>6000;

分析3: 升序

SELECT MAX(salary) 最高工资 , job_id
FROM employees
WHERE commission_pct IS NULL
GROUP BY job_id
HAVING MAX(salary)>6000
ORDER BY MAX(salary) ASC;

本系列是基于B站尚硅谷MySQL李玉婷教程的学习笔记,形成学习内容的文字版本。本篇的主要内容为常见函数、分组函数与分组查询的知识点讲解与实际案例。

5.安多个字段分组
案例:查询每个工种每个部门的最低工资,并按最低工资降序

题目中就是讲同一工种同一部门才是一组

SELECT MIN(salary)最低工资 , job_id , department_id
FROM employees
GROUP BY job_id,department_id;

7.连接查询

/*
多表查询,多表连接

内连接:
等值连接
非等值连接
自连接
外连接
左外连接
右外连接
全外连接

交叉连接
*/

一、内连接 P281

/*
语法:
select 查询列表
from 表名1 别名1,表名2 别名2…
where 等值连接条件
特点:
1.为解决重名问题,往往会起别名
2.表的顺序无要求

*/

# 一、等值连接 P281
/*
语法:
	select 查询列表
	from 表名1 别名1,表名2 别名2...
	where 等值连接条件
特点:
	1.为解决重名问题,往往会起别名
	2.表的顺序无要求

*/
1.简单的两表连接
USE myemployees ;

案例:查询员工名和部门名

SELECT last_name,department_name
FROM employees e,departments d
WHERE e.`department_id`=d.`department_id`;
2.添加筛选条件
案例1: 查询部门编号>100的部门和所在的城市名

SELECT `department_name`,`city`
FROM departments d,locations l
WHERE d.`location_id`=l.`location_id`
AND d.`department_id`>100;

案例2:查询有奖金的员工名、部门名

SELECT `first_name`,`department_name`
FROM `employees` e , `departments` d
WHERE e.`department_id`=d.`department_id`
AND e.commission_pct IS NOT NULL;

案例3:查询城市名中的第二个字符为o的部门名和城市名

SELECT `department_name`,`city`
FROM `departments` d,`locations` l
WHERE d.`location_id`=l.`location_id`
AND city LIKE '_o%';
3.添加分组+筛选
案例1:查询每个城市的部门个数

SELECT COUNT(*) 部门个数,lo.`city`
FROM `departments` d,`locations` lo
WHERE d.`location_id`=lo.`location_id`
GROUP BY lo.`city`;

案例2:查询有奖金的每个部门的部门名和部门的领导编号和该部门的最低工资

SELECT d.`department_name`,e.`manager_id`,MIN(salary)
FROM `departments` d,`employees` e
WHERE d.`department_id`=e.`department_id`
GROUP BY e.`department_id`;
4.三表查询

案例:查询员工名、部门名,工种名

5.添加分组、筛选、排序
案例:查询那个部门的员工数>5,并按员工数降序

SELECT `department_name`,COUNT(*) 个数
FROM `employees` e,`departments` d
WHERE e.`department_id`=d.`department_id`
GROUP BY e.`department_id`
HAVING COUNT(*)>5
ORDER BY COUNT(*) DESC;
#-------------------SQL99语法---------------------
#一、内连接
/*
语法:
select 查询表名
from 表名1 别名

 **inner join**  表名2. 别名。。。
on 连接条件
where 筛选
group by 分组
having 分组后筛选
order by 排序
*/
1.简单的两表连接
USE myemployees ;

案例:查询员工名和部门名

SELECT last_name,department_name
FROM employees e  INNER JOIN departments d
WHERE e.`department_id`=d.`department_id`;
2.添加筛选条件
案例1: 查询部门编号>100的部门和所在的城市名

SELECT `department_name`,`city`
FROM departments d INNER JOIN locations l
WHERE d.`location_id`=l.`location_id`
AND d.`department_id`>100;
3.添加分组+筛选
案例1:查询每个城市的部门个数

SELECT COUNT(*) 部门个数,lo.`city`
FROM `departments` d  JOIN `locations` lo
ON d.`location_id`=lo.`location_id`
GROUP BY lo.`city`;
4.添加分组、筛选、排序
案例:查询那个部门的员工数>5,并按员工数降序

SELECT `department_name`,COUNT(*) 个数
FROM `employees` e JOIN `departments` d
ON e.`department_id`=d.`department_id`
GROUP BY e.`department_id`
HAVING COUNT(*)>5
ORDER BY COUNT(*) DESC;
#二、非等值连接
案例:查询部门编号在10-90之间的员工的工资级别,并按级别进行分组

SELECT * FROM sal_grade;
FROM employees e
JOIN sal_grade g
ON e.salary BETWEEN g.`min_salary` AND g.`max_salary`
WHERE e.department_id BETWEEN 10 AND 90
GROUP BY g.grade;
#三、自连接
案例:查询员工名和对应的领导名

SELECT e.`last_name`,m.`last_name`
FROM employees e
JOIN employees m
ON e.`manager_id`=m.`employee_id`;
#四、外连接
/*

说明:查询结果为主表中所有记录,如果从表有匹配项,则显示匹配项;如果从表没有匹配项,则显示null
应用场景:一般用于查询主表中有但从表没有的记录
特点:
1.外连接分主从表,两表顺序不能调换
2.左连接的话,左为主表,右链接右为主表

语法:
SELECT 查询表名
FROM 表一 别名
LEFT / RIGHT OUTER JOIN 表2 别名
ON 连接条件
WHERE 筛选条件;

特点:
1.外连接的查询结果 = 内连接的查询结果 + 主表有但从表没有的记录
2.区分主从表  left join,左边为主表;right join,右边为主表
3.外连接用于查询主表有但从表没有的记录


*/

USE girls;
#案例1:查询所有女神记录,以及对应的男神名称,如果没有对应,显示为null
#左连接
SELECT b.*,bo.*
FROM beauty b
LEFT JOIN boys bo ON b.`boyfriend_id` = bo.`id`;
#右连接
SELECT b.*,bo.*
FROM boy bo
LEFT JOIN beauty b ON b.`boyfriend_id` = bo.`id`;


#案例2:哪个女神没有男朋友
#左连接
SELECT b.*,bo.*
FROM beauty b
LEFT JOIN boys bo ON b.`boyfriend_id` = bo.`id`
WHERE bo.`id` IS NULL;

#案例3:查询那个部门没有员工,并显示其部门编号和部门名,并计数 
SELECT d.`department_id`, d.`department_name`,COUNT(*)
FROM departments d
LEFT JOIN employees e
ON D.`department_id`=E.`department_id`
WHERE e.`employee_id` IS NULL;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qdtLHHVf-1590408801080)(C:\Users\dafa\AppData\Roaming\Typora\typora-user-images\image-20200521203655648.png)]

8.子查询

出现在其他语句的内部的select语句,称为子查询或内查询;里面嵌套其他select语句的查询语句,称为主查询或外查询。

子查询不一定必须出现在select语句内部,只是出现在select语句内部的时候较多!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0lqyy4GF-1590408801084)(C:\Users\dafa\AppData\Roaming\Typora\typora-user-images\image-20200521205055030.png)]

*分类:*

*单行子查询*

​ 特点:子查询的结果集只有一行一列

*多行子查询*

​ 特点:子查询的结果集有多行一列

按位置分类:

  • select 后面

    ​ 要求子查询的结果为单行单列(标量子查询)

  • FROM后面

    ​ 要求自持挨训的结果可以为多行多列

  • WHERE / HAVING 后面

    ​ 要求:自查询的结果必须为单列

    ​ 单行子查询

    ​ 多行子查询

  • EXISTS后面

    ​ 要求:子查询结果必须为单列(相关子查询)

*说明:*

​ 1、子查询语句需要放在小括号内,提高代码的阅读性

​ 2、子查询先于主查询执行,一般来讲,主查询会用到子查询的结果

​ 3、如果子查询放在条件中,一般来讲,子查询需要放在条件的右侧

​ 示例:where job_id>(子查询)

​ 不能写成:where (子查询)<job_id

​ 4、单行子查询对应的使用单行操作符:> < >= <= = <>

​ 多行子查询对应的使用多行操作符:in 、any 、all 、not in

LIMIT用来限定查询结果的起始行,以及总行数。

#一、放在WHERE后面
1.单行子查询
#案例1:查询Zlotkey的部门编号
#步骤1.查询部门编号
SELECT department_id
FROM employees
WHERE last_name='Zlotkey';

#步骤2.查询department_id=1中的员工姓名和工资
SELECT last_name,salary
FROM employees
WHERE department_id =(

	SELECT department_id
	FROM employees
	WHERE last_name='Zlotkey'

)

#案例2:查询工资比公司平均工资高的员工的员工号,姓名和工资
#步骤1:先算出公司平均工资,做步骤2的筛选项
SELECT AVG(salary)
FROM employees;

#步骤2:选出工号姓名工资
SELECT employee_id,last_name,salary
FROM employees
WHERE salary >(

	SELECT AVG(salary)
	FROM employees

);

#练习题:
#案例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,job_id,salary
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
WHERE salary > (
	SELECT MIN(salary)
	FROM employees
	WHERE department_id = 50
);
2.多行子查询
/*
in:判断某字段是否在指定列表内
x in(10,30,50)
any/some:判断某字段是否满足其中任意一个
x>any(10,20,60) 就等于 x >min(10,20,60)

x = any(10,20,60) 就等于 x in (10,20,60)

all : 是否满足所有


*/

#多行子查询
#题目:返回location_id是1400或1700的部门中的所有员工姓名
#步骤1
SELECT department_id
FROM departments
WHERE location_id IN (1400,1700)
#步骤2
SELECT last_name
FROM employees
WHERE department_id IN(
	SELECT department_id
	FROM departments
	WHERE location_id IN (1400,1700)
);

#题目:返回其它部门中比job_id为‘IT_PROG’部门任一工资低的员工的员工号、姓名、job_id 以及salary
#步骤1:选出工资

#步骤2:比较

```mysql
SELECT salary
FROM employees
WHERE job_id = 'It_PROG';
```

#步骤2:比较

```mysql
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'

);
```

#题目:返回其它部门中比job_id为‘IT_PROG’部门所有工资都低的员工 的员工号、姓名、job_id 以及salary
#步骤1:选出工资
SELECT salary
FROM employees
WHERE job_id = 'It_PROG';
#步骤2:比较
SELECT employee_id,last_name,job_id,salary
FROM employees
WHERE job_id !='IT_PROG'
AND salary < ALL(

	SELECT salary
	FROM employees
	WHERE job_id = 'IT_PROG'

);
#二、放在SELECT后面(P292)
#案例:查询部门编号是50的员工个数

SELECT (
	SELECT COUNT(*)
	FROM employees
	WHERE department_id = 50
	)
个数;
#三、放在FROM后面
#案例:查询每个部门的平均工资的工资级别

#步骤1
SELECT AVG(salary),department_id
FROM employees
GROUP BY department_id;

#步骤2:非等值连接,
SELECT dep_ag.department_id,dep_ag.ag,g.grade
FROM sal_grade g
JOIN (
	SELECT AVG(salary) ag,department_id
	FROM employees
	GROUP BY department_id
) dep_ag
ON dep_ag.ag BETWEEN g.min_salary AND g.max_salary;
#四、放在EXISTS后面
#案例1:查询有误张三丰的员工信息
SELECT EXISTS(
	SELECT *
	FROM employees
	WHERE last_name = '张三丰'
) 有无张三丰;

#案例2:查询有没有女朋友的男神信息
USE girls;

SELECT bo.*
FROM boys bo
WHERE bo.`id` IN(
	SELECT boyfriend_id
	FROM beauty b
	);

子查询经典案例

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f1lDuJWm-1590408801087)(C:\Users\dafa\AppData\Roaming\Typora\typora-user-images\image-20200522145156065.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-imVOqvoj-1590408801089)(C:\Users\dafa\AppData\Roaming\Typora\typora-user-images\image-20200522145223313.png)]

#练习题:
#1.查询和 Zlotkey相同部门的员工姓名和工资
SELECT last_name,salary
FROM employees
WHERE department_id = (
	SELECT department_id
	FROM employees
	WHERE last_name = 'Zlotkey'
);
#2.查询工资比公司平均工资高的员工的员工号,姓名和工资
SELECT employee_id,last_name,salary
FROM employees
WHERE salary > (
	SELECT AVG(salary)
	FROM employees
);


#3.查询各部门中工资比本部门平均工资高的员工的员工号,姓名和工资


SELECT employee_id,last_name,salary
FROM employees e
JOIN (
	SELECT department_id,AVG(salary) ag
	FROM employees
	GROUP BY department_id
)dep_ag
ON e.department_id =dep_ag.department_id
WHERE e.`salary` > dep_ag.ag;



#4.查询和姓名中包含字母u的员工在相同部门的员工的员工号和姓名
SELECT employee_id,last_name
FROM employees
WHERE department_id IN (
	SELECT department_id
	FROM employees
	WHERE last_name LIKE '%u%'
);


#5.查询在部门的 location id为1700的部门工作的员工的员工号
SELECT employee_id
FROM employees
WHERE department_id IN (
	SELECT DISTINCT department_id
	FROM departments 
	WHERE location_id = 1700
);

#6.查询管理者是King的员工姓名和工资
SELECT last_name,salary
FROM employees
WHERE manager_id IN (
	SELECT employee_id
	FROM employees
	WHERE last_name = 'K_ing'
);



#7.查询工资最高的员工的姓名,要求 firstname和 last name显示为一列,列名为姓名

SELECT CONCAT(first_name,last_name)'姓名'
FROM employees
WHERE salary = (
	SELECT MAX(salary)
	FROM employees
);

9.分页查询

/*
应用场景:当页面上的数据一页显示不全,则需要分页显示

语法:
select 
from 
join
on
where
group by
having
order by 
limit  起始条目索引,显示条目数

执行顺序:
1.from
2.join
3.on
4.where
5.group by
6.having
7.select
8.order by
9.limit

特点:
1.起始条目索引从0开始,不写默认从0
2.参数1:起始条目索引;参数2:显示条目数

公式:
加入要显示的页数的page,每页显示的条目数为size

select *
from 表名
limit (page-1)*size , size;
# -1主要就是因为从计数

*/

# 案例1 : 查询员工信息表的前5条
SELECT * FROM employees LIMIT 0,5;
等价于
SELECT * FROM employees LIMIT 5;

# 案例2:插叙有奖金的且工资较高的第11名到第20名
SELECT * FROM employees
WHERE commission_pct IS NOT NULL
ORDER BY salary DESC
LIMIT 10,10;

10.union联合查询

/*
说明:当查询结果来自于多张表,但多张表之间没有关系,这个时候就用联合查询

语法:
select 查询 from 表1   where 筛选条件
	union
select 查询 from 表2   where 筛选条件

特点:
1.需要注意查询列表的数量一致
2.union可以自动去重,加all 可以取消自动去重
*/

# 案例1:查询所有国家的年龄》20岁的用户信息

SELECT * FROM chinese WHERE age>20
UNION
SELECT * FROM usa WHERE uage >20;

# 案例2:查询所有国家的用户姓名和年龄
SELECT uname,uage FROM usa
UNION
SELECT 'name',age FROM chinese;
# 需要注意查询列表的数量一致

# 案例3:union可以自动去重
SELECT 1,'haha'
UNION
SELECT 1,'haha'
UNION
SELECT 1,'haha'
UNION
SELECT 1,'haha';
# 加all 可以取消自动去重
SELECT 1,'haha'
UNION ALL
SELECT 1,'haha'
UNION ALL
SELECT 1,'haha'
UNION ALL
SELECT 1,'haha';

二、DDL

Date Define Language ,用于对数据库和表的管理和操作

1.库的管理

#一、如何创建库
CREATE DATABASE studb;
#提高容错性,在java中用下面语句写
CREATE DATABASE IF NOT EXISTS studb;


#二、如何删除库
DROP DATABASE studb;
DROP DATABASE IF NOT EXISTS studb;

2.表的管理

#一、创建表

语法:
CREATE TABLE 表名(
	字段名  字段类型  【字段约束】,
	字段名  字段类型  【字段约束】,
	字段名  字段类型  【字段约束】,
	字段名  字段类型  【字段约束】,
	字段名  字段类型  【字段约束】
	);
	
#(无约束)案例:创建一个学生信息表
CREATE TABLE IF NOT EXISTS stuinfo(
	stuid INT ,
	stuname VARCHAR(20),
	gender CHAR,
	email VARCHAR(20),
	borndate DATETIME
	);

DESC stuinfo;

# 2.常见约束-6大约束
说明:用于限制表中字段的数据的,从而进一步保证数据表的数据是一致的准确的
NOT NULL 非空 :限制字段为必填项
DEFAULT 默认 : 用于限制该字段没有显式插入值,则直接显式默认值
PRIMARY KEY 主键 :用于限制该字段的值不能重复,并默认不能为空,一个表只能有一个主键
UNIQUE 唯一 : 用于限制该字段的值不能重复,一个表可以有n个
CHECK 检查 : 用于限制该字段的值必须满足指定条件,mysql不支持CHECK命令,但是也不报错
	CHECK(age BETWEEN 1 AND 100)
FOREIGN KEY 外键 : 用于限制两个表的关系,要求外键列的值必须来自于主表的关联列
	要求:1.主表关联列和从表的关联列的类型必须一致,意思一样
	     2.主表的关联列要求必须是主键
         
#(有约束)案例:
CREATE TABLE IF NOT EXISTS stu_info(
	stuid INT PRIMARY KEY ,       # 添加主键约束
	stuname VARCHAR(20) UNIQUE NOT NULL,   # 添加唯一约束+非空约束,可以叠加
	gender CHAR(1) DEFAULT '男',  # 添加默认约束
	email VARCHAR(20) NOT NULL,
	borndate DATETIME,
	age INT CHECK(age BETWEEN 0 AND 100) , # 添加检查约束,mysql不支持
	majorid INT,
	CONSTRAINT fk_stu_info_major FOREIGN KEY (majorid) REFERENCES major(id) # 外键
	);
	
	
#案例:不同方式添加主键
CREATE TABLE IF NOT EXISTS stu_info(
	stuid INT ,
	stuname VARCHAR(20) UNIQUE NOT NULL,   # 添加唯一约束+非空约束,可以叠加
	gender CHAR(1) DEFAULT '男',  # 添加默认约束
	email VARCHAR(20) NOT NULL,
	borndate DATETIME,
	age INT CHECK(age BETWEEN 0 AND 100) , # 添加检查约束,mysql不支持
	majorid INT,
    primary key(stuid),  # 添加主键
    constraint uq unique (stuname) , #添加唯一键
	CONSTRAINT fk_stu_info_major FOREIGN KEY (majorid) REFERENCES major(id) # 外键
	);

外键的设置:

主表[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9P6q6WKt-1590408801091)(C:\Users\dafa\AppData\Roaming\Typora\typora-user-images\image-20200522181615203.png)]

选择[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4ZyFduT6-1590408801092)(C:\Users\dafa\AppData\Roaming\Typora\typora-user-images\image-20200522181639263.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-th0SdEzN-1590408801093)(C:\Users\dafa\AppData\Roaming\Typora\typora-user-images\image-20200522181701235.png)]

#二、修改表

语法:ALTER TABLE 表名 ADD | MODIFY | CHANGE | DROP COLUMN 字段名  字段类型  【字段约束】

#1.修改表名

ALTER TABLE stuinfo RENAME TO students;

#2.添加字段

ALTER TABLE students ADD COLUMN borntime TIMESTAMP NOT NULL;
ALTER TABLE students DROP COLUMN borntime ;

DESC students;

#3.修改字段名

ALTER TABLE students CHANGE COLUMN borndate birthday DATETIME NULL; 

#4.修改字段类型

ALTER TABLE students MODIFY COLUMN birthday TIMESTAMP ;
DESC students;

#5.删除字段
ALTER TABLE students DROP COLUMN birthday ;


#三、删除表

DROP TABLE IF EXISTS students;

#四、复制表

#复制表结构
CREATE TABLE newTable LIKE stu_info;

#复制表的结构加数据
CREATE TABLE newTable2 SELECT * FROM girls.`beauty`;

#案例:复制employees表中的last_name,department_id,salary字段到新表emp
CREATE TABLE emp
SELECT last_name,department_id,salary
FROM myemployees.`employees`
WHERE 1=2;

常用类型:

  • int(10):整型,括号内显示的是宽度是10,也可以不写括号
    • tinyint:
    • smallint:
    • bigint:
  • double/float:浮点型,例如double(5,2)表示最多5位,其中必须有2位小数,即最大值为999.99;
  • **decimal:**浮点型,精度更高,在表示钱方面使用该类型,因为不会出现精度缺失问题;
  • char:固定长度字符串类型;char(4) 范围是0-255
  • varchar:可变长度字符串类型;
  • text:字符串类型;表示存储较长文本
意思格式n的解释特点效率
Char固定长度字符Char(n)最大的字符个数,可选默认:1不管实际存储,开辟的空间都是n个字符
Varchar可变长度字符Varchar(n)最大的字符个数,必选根据实际存储决定开辟的空间
  • **blob:**字节类型;//jpg mp3 avi 存储图片型
  • date:日期类型,格式为:yyyy-MM-dd;
  • time:时间类型,格式为:hh:mm:ss
  • timestamp/datetime:时间戳类型;日期+时间 yyyyMMdd hhmmss
保存范围所占字节
Datetime1900-1-1~xxxx年8
Timestamp1970-1-1~2038-12-314
# 测试题
#1.使用分页查询实现,查询员工信息表中的部门为50号的工资最低的5名员工的信息

SELECT * FROM employees 
WHERE department_id = 50 
ORDER BY salary 
LIMIT 5;

#2.使用子查询实现城市为'Seattle'的,且工资>10000的员工姓名
#步骤1:查询城市toroto的部门编号,需要使用内连接
SELECT department_id
FROM departments d
JOIN locations l ON d.`location_id`=l.`location_id`
WHERE city = 'Seattle';
#步骤2:查询部门号在1中的员工姓名
SELECT last_name
FROM employees
WHERE salary > 10000
AND
department_id IN (
	SELECT department_id
	FROM departments d
	JOIN locations l ON d.`location_id`=l.`location_id`
	WHERE city = 'Seattle'
);

#3.创建表qqinfo,里面包含qqid,添加主键约束(昵称nickname),添加唯一约束、邮箱email(非空)、性别gender

CREATE TABLE IF NOT EXISTS qqinfo (
	nickname VARCHAR(20) PRIMARY KEY,
	qqid INT,
	email VARCHAR(20) UNIQUE NOT NULL,
	gender CHAR(2)
	);

#4.删除表qqinfo

DROP TABLE IF EXISTS qqinfo;

#5.试写出sql查询语句的定义顺序和执行顺序
SELECT DISTINCT 查询列表
FROM 表名 别名
JOIN 连接表
ON 连接条件
WHERE 筛选条件
GROUP BY 分组列表
HAVING 分组后筛选
ORDER BY 排序
LIMIT 条目数;

执行顺序:
1.from
2.join 
3.on
4.where
5.group BY
6.having
7.select
8.order BY
9.limit

三、DML

/*
DML数据操纵语言:对表中的数据的增删改
*/

1.数据的插入


/*
语法:
单行的插入:
	insert into 表名(字段名1,字段名2,...)values(值1,值2...);
多行的插入:
	insert into 表名(字段名1,字段名2,...)
	values(值1,值2...),
	      (值1,值2...),
	      (值1,值2...);

特点:
1.字段和值列表一一对应:包含类型、约束等必须匹配
2.数值型的值,不用单引号;非数值型的必须使用单引号
3.字段顺序无要求
*/
#案例:字段和值列表一一对应:包含类型、约束等必须匹配
INSERT INTO stu_info(stuid,stuname,gender,email,borndate,age,majorid)
VALUES(9,'易烊','男','yi@qq.com','2000/11/27',20,1);

#案例2:可以为空的字段怎么插入,还是一一对应,去掉为空的字段或者值使用NULL
INSERT INTO stu_info(stuid,stuname,email,borndate,age,majorid)
VALUES(10,'易千','yi@qq.com','2000/11/27',20,1);
INSERT INTO stu_info(stuid,stuname,gender,email,borndate,age,majorid)
VALUES(8,'易烊',NULL,'yi@qq.com','2000/11/27',20,1);

#案例3:默认字段如何插入,值使用default
INSERT INTO stu_info(stuid,stuname,gender,email,borndate,age,majorid)
VALUES(8,'易烊',DEFAULT,'yi@qq.com','2000/11/27',20,1);

#案例4:可以省略字段列表,默认所有字段
INSERT INTO stu_info VALUES(11,'易烊','男','yi@qq.com','2000/11/27',20,1);

补充:自增的设置

/*
1.自增长列设置在一个键上,比如主键或唯一键
2.自增长列数据类型必须为唯一型
3.一个表最多有一个自增长列
*/
#1.图形界面勾选
#2.创建表的后边直接跟AUTO_INCREMENT
CREATE TABLE gradeinfo(
	gradeID INT PRIMARY KEY AUTO_INCREMENT,
	gradeName VARCHAR(20)
	);
INSERT INTO gradeinfo(gradeName) VALUES('一年级'),('二年级'),('三年级');

2.数据的修改 P105

/*
1.修改单表的记录
语法:
update 表名
set 列=新值,列=新值,列=新值,...
where 筛选条件;
2.修改多表的记录

语法:
SQL92语法:
update 表1 别名,表2 别名
set 列=值
where 连接条件 
and 筛选条件

SQL99语法:
update 表1 别名
inner | left | right join 表2 别名
on 连接条件
set 列=值,...
where 筛选条件;

*/

#a.修改单表的记录
#案例1:修改beauuty表中姓王的女生的电话为13525764896
UPDATE beauty SET phone='13525764896'
WHERE NAME LIKE '王%';

#案例2:修改boys表中id=2的姓名张飞,魅力值12
UPDATE boys SET boyname='郑飞',userCP=10
WHERE id=2;

#b.修改多表的记录
#案例1:修改张无忌的女朋友的手机号为114

UPDATE boys bo
INNER JOIN beauty b
ON bo.`id`=b.`boyfriend_id`
SET b.`phone`=114
WHERE bo.`boyName`='张无忌';

#案例2:修改没有男朋友的女生的男朋友为郑飞
UPDATE boys bo
RIGHT INNER JOIN beauty b
ON bo.`id`=b.`boyfriend_id`
SET b.boyfriend_id = 2
WHERE b.id IS NULL ;

3.数据的删除 P306

/*
方式1:delete语句
	delete from 表名 where 筛选条件;
	一删一行

方式2:truncate语句
	truncate table 表名;

*/

#案例1:删除姓李的所有信息
DELETE FROM stu_info WHERE stuname LIKE '易千%';

#案例2:删除表的所有信息
TRUNCATE TABLE newtable2;

#【面试题】delete语句与truncate语句的区别

1.delete可以添加WHERE条件,逐行删,TRUNCATE一次性清除所有语句
2.truncate效率高
3.如果删除带自增长列的表,
	使用DELETE删除,重新插入数据,记录从断点开始
	使用TRUNCATE删除,重新插入数据,记录从1开始
4.delete删除数据会返回受影响的行数
  TRUNCATE删除数据不会返回受影响的行数
5.delete删除数据,支持事务回滚,TRUNCATE删除数据不事务回滚

四、事务

事务属于TCL控制语言(Transaction Control Language )。

*一个事务是由一条或者多条sql语句构成,这一条或者多条sql语句要么全部执行成功,要么全部执行失败!*

默认情况下,每条单独的sql语句就是一个单独的事务!

事务的四大特性(ACID)

  • 原子性(Atomicity):事务中所有操作是不可再分割的原子单位。事务中所有操作要么全部执行成功,要么全部执行失败。
  • 一致性(Consistency):事务执行后,数据库状态与其它业务规则保持一致。如转账业务,无论事务执行成功与否,参与转账的两个账号余额之和应该是不变的。
  • 隔离性(Isolation):隔离性是指在并发操作中,不同事务之间应该隔离开来,使每个并发中的事务不会相互干扰。
  • 持久性(Durability):一旦事务提交成功,事务中所有的数据操作都必须被持久化到数据库中,即使提交事务后,数据库马上崩溃,在数据库重启时,也必须能保证通过某种机制恢复数据。
/*
概念:一个事务是由一条或者多条sql语句构成,
这一条或者多条sql语句要么全部执行成功,要么全部执行失败

分类:
1.隐式事务
	没有明显的开启和结束标记,比如DML语句的insert,update,delete本身就是一条事务
	例如:
	INSERT INTO stu_info(stuid,stuname,gender,email,borndate,age,majorid)
VALUES(8,'易烊',DEFAULT,'yi@qq.com','2000/11/27',20,1);


2.显式事务
	具有明显的开启和结束标记
	一般由多条SQL语句组成

	步骤:
	0.取消隐式事务自动开启的功能
	a.开启事务
	b.编写事务需要的SQL语句
	c.结束事务

*/

SHOW VARIABLES LIKE '%auto%'

#事务使用步骤演示
#0.取消隐式事务自动开启的功能
SET autoocommit = 0

#a.开启事务
START TRANSACTION;

#b.编写事务需要的SQL语句
#张三丰-5000,灭绝师太+5000
UPDATE stu_info SET balance = balance-5000 WHERE stuid=1;
UPDATE stu_info SET balance = balance+5000 WHERE stuid=2; 

#c.结束事务
#-提交:
COMMIT;

#-回滚
ROLLBACK;

yname=‘郑飞’,userCP=10
WHERE id=2;

#b.修改多表的记录
#案例1:修改张无忌的女朋友的手机号为114

UPDATE boys bo
INNER JOIN beauty b
ON bo.id=b.boyfriend_id
SET b.phone=114
WHERE bo.boyName=‘张无忌’;

#案例2:修改没有男朋友的女生的男朋友为郑飞
UPDATE boys bo
RIGHT INNER JOIN beauty b
ON bo.id=b.boyfriend_id
SET b.boyfriend_id = 2
WHERE b.id IS NULL ;


### 3.数据的删除 P306

```mysql
/*
方式1:delete语句
	delete from 表名 where 筛选条件;
	一删一行

方式2:truncate语句
	truncate table 表名;

*/

#案例1:删除姓李的所有信息
DELETE FROM stu_info WHERE stuname LIKE '易千%';

#案例2:删除表的所有信息
TRUNCATE TABLE newtable2;

#【面试题】delete语句与truncate语句的区别

1.delete可以添加WHERE条件,逐行删,TRUNCATE一次性清除所有语句
2.truncate效率高
3.如果删除带自增长列的表,
	使用DELETE删除,重新插入数据,记录从断点开始
	使用TRUNCATE删除,重新插入数据,记录从1开始
4.delete删除数据会返回受影响的行数
  TRUNCATE删除数据不会返回受影响的行数
5.delete删除数据,支持事务回滚,TRUNCATE删除数据不事务回滚

四、事务

事务属于TCL控制语言(Transaction Control Language )。

*一个事务是由一条或者多条sql语句构成,这一条或者多条sql语句要么全部执行成功,要么全部执行失败!*

默认情况下,每条单独的sql语句就是一个单独的事务!

事务的四大特性(ACID)

  • 原子性(Atomicity):事务中所有操作是不可再分割的原子单位。事务中所有操作要么全部执行成功,要么全部执行失败。
  • 一致性(Consistency):事务执行后,数据库状态与其它业务规则保持一致。如转账业务,无论事务执行成功与否,参与转账的两个账号余额之和应该是不变的。
  • 隔离性(Isolation):隔离性是指在并发操作中,不同事务之间应该隔离开来,使每个并发中的事务不会相互干扰。
  • 持久性(Durability):一旦事务提交成功,事务中所有的数据操作都必须被持久化到数据库中,即使提交事务后,数据库马上崩溃,在数据库重启时,也必须能保证通过某种机制恢复数据。
/*
概念:一个事务是由一条或者多条sql语句构成,
这一条或者多条sql语句要么全部执行成功,要么全部执行失败

分类:
1.隐式事务
	没有明显的开启和结束标记,比如DML语句的insert,update,delete本身就是一条事务
	例如:
	INSERT INTO stu_info(stuid,stuname,gender,email,borndate,age,majorid)
VALUES(8,'易烊',DEFAULT,'yi@qq.com','2000/11/27',20,1);


2.显式事务
	具有明显的开启和结束标记
	一般由多条SQL语句组成

	步骤:
	0.取消隐式事务自动开启的功能
	a.开启事务
	b.编写事务需要的SQL语句
	c.结束事务

*/

SHOW VARIABLES LIKE '%auto%'

#事务使用步骤演示
#0.取消隐式事务自动开启的功能
SET autoocommit = 0

#a.开启事务
START TRANSACTION;

#b.编写事务需要的SQL语句
#张三丰-5000,灭绝师太+5000
UPDATE stu_info SET balance = balance-5000 WHERE stuid=1;
UPDATE stu_info SET balance = balance+5000 WHERE stuid=2; 

#c.结束事务
#-提交:
COMMIT;

#-回滚
ROLLBACK;
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值