[MySQL]基础篇

news2024/11/17 6:30:49

文章目录

  • 1. MySQL基本使用
    • 1.1 MySQL的启动和登录
      • 1.1.1 MySQL的启动
      • 1.1.2 MySQL的客户端连接
    • 1.2 数据模型
  • 2. SQL
    • 2.1 SQL类型
      • 2.1.1 数值类型
      • 2.1.2 字符串类型
      • 2.1.3 日期类型
    • 2.2 DDL
      • 2.2.1 数据库操作
      • 2.2.2 表操作 - 查询
      • 2.2.3 表操作 - 创建表
      • 2.2.4 表操作 - 修改
    • 2.3 DML
      • 2.3.1 添加数据
      • 2.3.2 修改数据
      • 2.3.3 删除数据
    • 2.4 DQL
      • 2.4.1 基本查询
      • 2.4.2 条件查询
      • 2.4.3 聚合函数
      • 2.4.4 分组查询
      • 2.4.5 排序查询
      • 2.4.6 分页查询
      • 2.4.7 执行顺序
    • 2.5 DCL
      • 2.5.1 管理用户
      • 2.5.2 权限控制
  • 3. 函数
    • 3.1 字符串函数
    • 3.2 数值函数
    • 3.3 日期函数
    • 3.4 流程控制函数
  • 4. 约束
    • 4.1 概念
    • 4.2 案例
    • 4.3 外键约束
  • 5. 多表查询
    • 5.1 连接查询
      • 5.1.1 内连接
      • 5.1.2 外连接
      • 5.1.3 自连接
    • 5.2 联合查询
    • 5.3 子查询
      • 5.3.1 标量子查询
      • 5.3.2 列子查询
      • 5.3.3 行子查询
      • 5.3.4 表子查询
    • 5.4 多表查询案例
  • 6. 事务
    • 6.1 事务的基本操作
    • 6.2 并发事务问题
    • 6.3 事务的隔离级别


1. MySQL基本使用


1.1 MySQL的启动和登录


1.1.1 MySQL的启动

1. 管理员身份打开cmd

net start mysql80 ##启动MySQL
net stop mysql80 ##关闭MySQL

1.1.2 MySQL的客户端连接

1. 管理员身份打开cmd

mysql [-h 127.0.0.1] [-P 3306] -u root -p 

使用这种方法需要配置环境变量,MySQL的bin目录

2. 打开mysql命令行客户端,输入密码以打开


1.2 数据模型

关系型数据库 (RDBMS)

  • 概念 : 建立在关系模型基础上,由多张相互连接的二维表组成的数据库
  • 特点 :
    1. 使用表存储数据,格式同意,便于维护
    2. 使用SQL语言操作,标准统一,使用方便

2. SQL

SQL通用语法

  1. SQL语句可以单行或多行书写,以分号结尾
  2. SQL依据可以使用空格/TAB增强可读
  3. MySQL数据库的SQL语句不区分大小写,关键字建议大写
  4. 注释:
    • 单行注释 : --注释内容 / # 注释内容(MySQL特有)
    • 多行注释: /*注释内容*/
分类全称说明
DDLData Definition Language数据定义语言,用来定义数据库对象(数据库,表,字段)
DMLData Manipulation Language数据操作语言,用来对数据库表中的数据进行增删改
DQLData Query Language数据查询语言,用来查询数据库中表的记录
DCLData Control Language数据控制语言,用来创建数据库用户、控制数据库的访问权限

如果您需要其他格式或有其他问题,请随时告诉我。

2.1 SQL类型

2.1.1 数值类型

类型大小有符号范围无符号范围描述
tinyint1 byte(-128,127)(0, 255)小整数值
smallint2 bytes(-32768,32767)(0, 65535)大整数值
mediumint3 bytes(-8388608,8388607)(0, 16777215)大整数值
int/integer4 bytes(-2147483648,2147483647)(0, 4294967295)大整数值
bigint8 bytes(-263,263-1)(0, 2^64-1)极大整数值
float4 bytes(-3.402823466 E+38,3.402823466351 E+38)(0, 3.402823466 E+38)单精度浮点数值
double8 bytes(-1.7976931348623157 E+308,1.7976931348623157 E+308)(0, 1.7976931348623157 E+308)双精度浮点数值
decimal依赖于M和D的值依赖于M和D的值依赖于M和D的值小数值(精确定点数)

ps :

  • decimal : 123.45 精度(M)为5,标度(D)为2
  • 无符号类型写法: tinyint unsigned
double(4,1)

4代表整体长度,1代表小数点后的位数


2.1.2 字符串类型

类型大小描述
char0-255 bytes定长字符串
varchar0-65535 bytes变长字符串
tinyblob0-255 bytes不超过255个字符的二进制数据
tinytext0-255 bytes短文本字符串
blob0-65,535 bytes二进制形式的长文本数据
text0-65,535 bytes长文本数据
mediumblob0-16,777,215 bytes二进制形式的中等长度文本数据
mediumtext0-16,777,215 bytes中等长度文本数据
longblob0-4,294,967,295 bytes二进制形式的极大文本数据
longtext0-4,294,967,295 bytes极大文本数据

ps :

  • char性能优与varchar
    变长是指,在不超过最大容量时,1就是1,2就是2
    定长是指,哪怕是1,也要占用最大容量

2.1.3 日期类型

类型大小范围格式
date31000-01-01 至 9999-12-31YYYY-MM-DD
time3-838:59:59 至 838:59:59HH:MM:SS
year11901 至 2155YYYY
datetime81000-01-01 00:00:00 至 9999-12-31 23:59:59YYYY-MM-DD HH:MM:SS
timestamp41970-01-01 00:00:01 至 2038-01-19 03:14:07YYYY-MM-DD HH:MM:SS

2.2 DDL

2.2.1 数据库操作

#查询
show databases; # 查询所有数据库
select database(); #查询当前数据库


#创建
create database [if not exists] 数据库名 [default charset 字符集] [collate 排序规则];

#eg:
creat datebase if not exists emp default charset utf8mb4;


#删除
drop database [if exists] 数据库名;


#使用
use 数据库名

MySQL里实现的utf8最长使用3个字节,utf8mb4 是 utf8 的超集并完全兼容utf8,能够用四个字节存储更多的字符。

比如:最常见的就算现在手机端常用的表情字符 emoji和一些不常用的汉字,如 “墅” ,这些需要四个字节才能编码出来。


2.2.2 表操作 - 查询

show tables; # 查询当前数据库的所有表

desc 表名; # 查询表结构

show create table 表名; # 查询指定表的建表语句

2.2.3 表操作 - 创建表

语法:

create table 表名(
	字段1 字段1的类型 [comment '注释内容'], #逗号
	...
	字段2 字段2的类型 [comment '注释内容']
	)

eg:创建一个如下表
在这里插入图片描述

create table tb_user(
	id int comment '编号',
	name varchar(50) comment '名字',
	age int comment '年龄',
	gender char(1) comment '性别',
	)comment '用户表';

eg: 根据需求创建表
员工信息表,要求:

  1. 编号(纯数字)
  2. 员工工号(字符串类型,长度不超过10位)
  3. 员工姓名(字符串类型,长度不超过10位)
  4. 性别
  5. 年龄
  6. 身份证号
  7. 入职时间(取值年月日即可)
create table emp(
	id int comment'编号',
	worknum varchar(10),
	name varchar(10),
	gender char(1),
	age tinyint unsigned,
	idcard char(18),
	entrydate date
	)

2.2.4 表操作 - 修改

#添加字段
alter table 表名 add 字段名 类型(长度) [comment 注释] [约束]; #添加字段

#eg : 为emp表增加一个新的字段 "昵称" 为nickname,类型为varchar(20)
alter table emp add nickname varchar(20) comment '昵称';


#修改字段
alter table 表名 modify 字段名 新数据类型(长度) # 修改数据类型
alter table 表名 change 旧字段名 新字段名 类型(长度) [comment 注释] [约束]; #修改字段名和字段类型

#eg : 将emp表的nickname字段修改为username,类型为varchar(30)
alter table emp change nickname username varchar(30) comment'昵称';


#删除字段
alter table 表名 drop 字段名;

#eg : 将emp表的字段username删除
alter table emp drop username;


#修改表名
alter table 表名 rename to 新表名;

#eg : 将emp表的表名修改为employee
alter table emp rename to employee;


#删除表
drop table [if exists] 表名;
truncate table 表名; ##删除指定表,并重新创建该表

2.3 DML

2.3.1 添加数据

insert into 表名(字段名1,字段名2,...) values(1,2,...); #给指定字段添加数据
#eg:
insert into emp(id,worknum,name,gender,age) values(1,'1','9tse','男',19);

insert into 表名 values(1,2,...); #给全部字段添加数据
#eg:
insert into emp values(2,'2','sewerperson','男',20);

insert into 表名(字段名1,字段名2,...) values(1,2,...),(1,2,...)...;
insert into 表名 values(1,2,...),(1,2,...)...;
#eg:
insert into emp values(1,'1','9tse','男',19),(2,'2','sewerperson','男',20);

ps:

  1. 插入数据时,指定的字段顺序需要与值的顺序对应
  2. 字符串和日期数据应该包含在引号中
  3. 插入数据大小,应在字段的规定范围内

2.3.2 修改数据

update 表名 set 字段名1 =1,字段名2 =2,... [where 条件];

#eg: 修改id为1的数据,将name修改为9tse
update emp set name = '9tse' where id = 1;
# 修改id为1的数据,将name修改为 sewer,gender修改为 女
update emp set name = 'sewer',gender = '女' where id = 1;
# 将所有员工的入职日期修改为2008-01-01
update emp set entrydate = '2008-01-01';

ps:

  • 修改语句的条件如果没有,默认修改整张表的所有数据

2.3.3 删除数据

delete from 表名 [where 条件];
#eg:删除gender为女的员工
delete from emp where gender = '女';
# 删除所有员工
delete from emp;

ps:

  1. delete语句的条件如果没有,默认作用于整张表的所有数据
  2. delete语句不能删除某一个字段的值(可以使用update)

2.4 DQL

语法:

select
	字段列表
from
	表名列表
where
	条件列表
group by
	分组字段列表
having
	分组后条件判断
order by
	排序字段列表
limit
	分页参数
  • 基本查询
  • 条件查询(where)
  • 聚合函数(count,max,min,avg,sum)
  • 分组查询(group by)
  • 排序查询(order by)
  • 分页查询(limit)

2.4.1 基本查询

#查询多个字段
select 字段1,字段2,字段3,... from 表名;
select * from 表名; #效率较低

#设置别名
select 字段1[as] 别名1,字段2[as] 别名2 ... from 表名;

#去除重复记录
select distinct 字段列表 from 表名;

eg:

#查询指定字段返回
select name,worknum,age from emp; 

#查询所有字段返回
select id,worknum,name,gender,age;
select * from emp; #尽量不写*,影响效率

#查询所有员工工作地址,起别名
select workaddress as '工作地址' from emp;
select workaddress '工作地址' from emp;

#查询工作员工的上班地址(不要重复)
select distinct workaddress '工作地址' from emp;

2.4.2 条件查询

语法:

select 字段列表 from 表名 where 条件列表;
比较运算符功能
>大于
>=大于等于
<小于
<=小于等于
=等于
<> 或 !=不等于
between…and…在某范围内(含最小,最大)
in(…)在in之后的列表中的值,多选一
like 占位符模糊匹配(_匹配单字符,%匹配任意个字符)
is null是NULL
逻辑运算符功能
AND 或 &&并且(多个条件同时成立)
OR 或 ||或者(多个条件任意一个成立)
NOT 或 !非不是

eg:

#查询年龄等于88的员工
select * from emp where age = 88;

#小于20
select * from emp where age < 20;

#查询没有身份证号的员工
select * from emp where idcard is null;

#有身份证号的员工
select * from emp where idcard is not null;

#年龄在15到20(包含)的员工
select * from emp where age >= 15 && age <= 20;
select * from emp where age between 15 and 20;

# 性别女且小于25
select * from emp where gender = '女' and age < 25;

#18 20 40 的
select * from emp where age = 18 || age = 20 || age = 40;
select * from emp where age in(18,20,40);

#名字是两个字的
select * from emp where name like '__';

#身份证号最后一位为X的
select from emp where idcard like '%X';

2.4.3 聚合函数

介绍: 将一列数据作为一个整体,进行纵向计算

函数功能
count统计数量
max最大值
min最小值
avg平均值
sum求和

语法

select 聚合函数(字段列表) from 表名;

ps : null值不参与聚合函数的运算

#统计员工数量
select count(*) from emp;
select count(idcard) from emp;

#统计平均年龄
select avg(age) from emp;

#最大年龄
select max(age) from emp;

#最小
select min(age) from emp;

#西安地区员工年龄之和
select sum(age) from emp where workaddress = '西安';

2.4.4 分组查询

语法:

select 字段列表 from 表名 [where 条件] group by 分组字段名 [having 分组后过滤条件];

wherehaving的区别

  • 执行实际不同:
    where是分组之前进行过滤,不满足where条件,不参与分组;
    having是分组后对结果进行过滤
  • 判断条件不同
    where不能对聚合函数进行判断
    having可以

执行顺序 : where > 聚合函数 > having
分组后,查询的字段一般为聚合函数和分组字段,查询其他字段无意义

#根据性别分组,统计男性员工和女性员工的数量
select gender,count(*) from emp group by gender;

#根据性别分组,统计男女平均年龄
select gender,avg(age) from emp group by gender;

#查询年龄小于45,根据工作地址分组,获取员工数量大于3的工作地址
select workaddress,count(*) address_count from emp where age < 45 group by workaddress having address_count >= 3;

2.4.5 排序查询

语法

select 字段列表 from 表名 group by 字段1 排序方式1, 字段2 排序方式2;

排序方式:

  1. asc : 升序(默认值)
  2. desc : 降序

ps: 如果是多字段排序,当第一个字段值相同时,才会根据第二个字段进行排序;

eg:

#根据年龄升序
select * from emp order by age asc;
select * from emp order by age;

#入职时间降序
select * from emp order by entrydate desc;

#年龄升序,相同则入职时间降序
select * from emp order by age asc , entrydate desc;

2.4.6 分页查询

语法

select 字段列表 from 表名 limit 起始索引,查询记录数;

ps:

  1. 起始索引从0开始,起始索引 = (查询页码-1) * 每页显示记录数
  2. 分页查询时数据库方言,不同数据库由不同的实现,MySQL时limit
  3. 如果查询的是第一页数据,起始索引可以省略,直接简写为 limit 10

eg:

#查询第一页员工数据,每页10条
select * from emp limit 0,10;
select * from emp limit 10;

#查询第二页,每页10
select * from emp limit 10,10;

#查询年龄为20,21,22,23岁的女性员工信息。
select * from emp where gender ='女' and age in(20,21,22,23);

#查询性别为 男 ,并且年龄在 20-40 岁(含)以内的姓名为三个字的员工。
select * from emp where gender = '男' and ( age between 20 and 40 ) and name like '___';

#统计员工表中,年龄小于60岁的 ,男性员工和女性员工的人数。
select gender,count(*) from emp where age < 60 group by gender;

#查询所有年龄小于等于35岁员工的姓名和年龄,并对查询结果按年龄升序排序,如果年龄相同按入职时间降序排序
select name , age from emp where age <= 35 order by age asc , entrydate desc;

#查询男,20-40 岁(含)以内的前5个员工信息 按年龄升序,相同按入职时间升序排序。
select * from emp where gender = '男' and age between 20 and 40 order by age asc , entrydate asc limit 5 ;

2.4.7 执行顺序

#查询年龄大于15的员工的姓名、年龄,并根据年龄进行升序排序
#通过设置别名和使用别名的方法进行验证
select e.name ename , e.age eage from emp e where e.age > 15 order by age asc;
#编写顺序
select
	字段列表
from
	表名列表
where
	条件列表
group by
	分组字段列表
having
	分组后条件判断
order by
	排序字段列表
limit
	分页参数
#执行顺序,selec跑到having后
from
	表名列表
where
	条件列表
group by
	分组字段列表
having
	分组后条件判断
select
	字段列表
order by
	排序字段列表
limit
	分页参数

2.5 DCL

2.5.1 管理用户

语法

#查询用户
use mysql;
select * from user;

#创建用户
create user '用户名'@'主机名' identified by '密码';

#修改用户密码
alter user '用户名'@'主机名' identified with mysal_native_password by '新密码';

#删除用户
drop user '用户名'@'主机名'

ps :

  • 主机名可以使用 % 通配
    使用这类SQL开发人员操作的比较少,主要是DBA (Database Administrator数据库管理员)

eg:

#创建用户 9tse ,只能够在当前主机Localhost访间,密码123456;
create user '9tse'@'localhost' identified by '123456':

#创建用户 sewer ,可以在任意主机访问该数据库,密码123456 ;
create user 'sewer'@'%' identified by '123456';

#修改用户 9tse 的访问密码为 1234 ;
alter user '9tse'@'%' identified with mysql_native_password by '1234';

#删除9tse@localhost用户
drop user'9tse'@'localhost'

2.5.2 权限控制

常用权限如下

权限说明
ALL, ALL PRIVILEGES所有权限
SELECT查询数据
INSERT插入数据
UPDATE修改数据
DELETE删除数据
ALTER修改表
DROP删除数据库/表/视图
CREATE创建数据库/表

语法

#查询权限
show grants for '用户名'@'主机名';

#授予权限
grant 权限列表 on 数据库名.表名 to '用户名'@'主机名';

#撤销权限
revoke 权限列表 on 数据库名.表名 from '用户名'@'主机名';

ps:

  1. 多个授权之间逗号隔开
  2. 授权时,数据库名和表名可以用通配符*表示所有;

eg:

-- 查询权限
show grants for '9tse'@'%';

-- 授予权限
grant all on sewerperson.* to '9tse'@'%';

-- 撤销权限
revoke all on sewerperson.* from '9tse'@'%';

3. 函数

3.1 字符串函数

函数功能
concat(s1, s2, … sn)字符串拼接,将s1,s2,… sn拼接成一个字符串
lower(str)将字符串str全部转为小写
upper(str)将字符串str全部转为大写
lpad(str, n, pad)左填充,用字符串pad对str的左边进行填充,达到n个字符串长度
rpad(str, n, pad)右填充,用字符串pad对str的右边进行填充,达到n个字符串长度
trim(str)去掉字符串头部和尾部的空格
substring(str, start, len)返回从字符串str从start位置起的len个长度的字符串

字符串函数的基本使用

-- concat
select concat('Hello''MysQL');

-- Tower
select lower('Hello'):

-- upper
select upper('Hello');

-- lpad
select Lpad('01'5,'-'); # ---01

-- rpad
select rpad('01'5,'-');

-- trim
select trim(' HelloMysQL');

-- substring
select substring('Hello MySL',1,5); # Hello

案例

-- 业务需求变更,员工的工号统一5位数,不足5位数的全部在前面补0。比如: 1号员工的工号应该为00001.
update emp set workno = lpad(workno,5,'0');

3.2 数值函数

函数功能
ceil(x)向上取整
floor(x)向下取整
mod(x; y)返回 x/y 的模
rand()返回 0~1 内的随机数
round(x; y)求参数 x 的四舍五入的值,保留 y 位小数

数值函数的基本利用

-- ceil
select ceil(1.1):

-- floor
select floor(1.9);

-- mod
select mod(7,4);

-- rand
select rand();

- round
select round(2.344,2);

案例

-- 案例:通过数据库的函数,生成一个六位数的随机验证码。select
lpad(round(rand()*1000000, 0), 6, '0'); 

3.3 日期函数

函数功能
curdate()返回当前日期
curtime()返回当前时间
now()返回当前日期和时间
year(date)获取指定 date 的年份
month(date)获取指定 date 的月份
day(date)获取指定 date 的日期
date_add(date, interval expr type)返回一个日期/时间值加上一个时间间隔 expr 后的时间值
datediff(date1, date2)返回起始时间 date1 和结束时间 date2 之间的天数

日期函数的基本使用

-- curtime()
select curtime();

 -- now()
select now();

-- YEAR,MONTH,DAY 
select YEAR(now());
select MONTH(now()); 
select DAY(now()); 

-- date_add
select date_add(now(), interval 70 year); 

-- datediff
select datediff('2021-10-01', '2021-12-01'); 

案例

-- 案例:查询所有员工的入职天数,并根据入职天数倒序排序。
select name, datediff(curdate(), entrydate) as 'entrydays' from emp order by entrydays desc; 

3.4 流程控制函数

函数功能
if(value , t, f)如果 value 为 true,则返回 t,否则返回 f
ifnull(value1, value2)如果 value1 不为空,返回 value1,否则返回 value2
case when [val1] then [res1] … else [default] end如果 val1 为 true,则返回 res1,… 否则返回 default 默认值
case [expr] when [val1] then [res1] … else [default] end如果 expr 的值等于 val1,则返回 res1,… 否则返回 default 默认值

流程控制函数的基本使用

--if
select if(false, '0k', 'Error'); 

-- ifnull
select ifnull('0k','Default');
select ifnull('','Default'); 
select ifnull(null,'Default'); 

案例

-- case when then elserend

-- 需求:查询emp表的员工姓名和工作地址(北京/上海————>一线城市,其他————>二线城市)
select
	name,
	(case workaddress when '北京' then '一线城市' when'上海' then '一线城市' else '二线城市'end)as'工作地址' 
from emp;
--案例: 统计班级各个学员的成绩,展示的规则如下:
-->= 85,展示松秀
-->= 60,展示及格
--否则,展示不及格

select
	id,
	name,
	(case when math >= 85 then '优秀' when math >=60 then '及格' else '不及格' end)'数学',
	(case when english >= 85 then '优秀' when english >=60 then '及格' else '不及格' end)'英语',
	(case when chinese >= 85 then '优秀' when chinese >=60 then '及格' else '不及格' end)'语文',
from score;

4. 约束

4.1 概念

概念 : 约束时作用于表中字段上的规则,用于限制存储在表中的数据
目的 : 保证数据库中数据的正确,有效性和完整性
注意 : 约束时作用于表中的字段上的,可以在创建表/修改表的时候添加约束.

约束描述关键字
非空约束限制该字段的数据不能为 nullnot null
唯一约束保证该字段的所有数据都是唯一、不重复的unique
主键约束主键是一行数据的唯一标识,要求非空且唯一primary key
默认约束保存数据时,如果未指定该字段的值,则采用默认值default
检查约束检查约束 (8.0.16 版本之后) 保证字段值满足某一个条件check
外键约束用来让两张表的数据之间建立连接,保证数据的一致性和完整性foreign key

4.2 案例

建表要求:

字段名字段含义字段类型约束条件约束关键字
idID唯一标识int主键,并且自动增长primary key auto increment
name姓名varchar(10)不为空,并且唯一not null, unique
age年龄int大于0,并且小于等于120check (age > 0 and age <= 120)
status状态char(1)如果没有指定该值,默认为1default ‘1’
gender性别char(1)
create table user(
	id int primary key auto_increment comment '主键',
	name varchar(10) not null unique comment '姓名' ,
	age int check ( age >  && age <= 120 ) comment'年龄'
	status char(1) default '1' comment'状态',
	gender char(1) comment '性别'
)comment'用户表';
insert into user(name,age,status,gender) values ('Tom1',19,'1','男'),('Tom2',25,'0','男');
insert into user(name,age,status,gender) values ('Tom3',19,1'男');

insert into user(name,age,status,gender) values (null,19,'1''男');
insert into user(name,age,status,gender) values ('Tom3',19,'1''男');

insert into user(name,age,status,gender) values ('Tom4',80,1',男');
insert into user(name,age,status,gender) values ('Tom5',-1,1',男');
insert into user(name,age,status,gender) values ('Tom5',121,'1''男');
insert into user(name,age,gender) values ('Tom5',120'男');

当不满足建表约束时就会报错 : 无法插入数据


4.3 外键约束

语法

#添加外键
create table 表名(
	字段名 数据类型,
	...
	[constraint] [外键名称] foreign key(外键字段名) references 主表(主表列名)
);

alter table 表名 add constraint 外键名称 foreign key(外键字段名) references 主表(主表列名);


#删除外键
alter table 表名 drop foreign key 外键名称;

案例

-- 添加外键
alter table emp add constraint fk_emp_dept_id foreign key (dept_id) references dept(id);
-- 删除外键
alter table emp drop foreign key fk_emp_dept_id;

实际中并不常用外键,会导致耦合度较高

删除更新行为的函数

行为说明
no action当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有则不允许删除/更新。(与restrict一致)
restrict当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有则不允许删除/更新。(与no action 一致)
cascade当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有,则也删除/更新外键在子表中的记录。
set null当在父表中删除对应记录时,首先检查该记录是否有对应外键,如果有则设置子表中该外键值为null (这就要求该外键允许取null)。
set default父表有变更时,子表将外键列设置成一个默认的值(Innodb不支持)。
alter table 表名 add constraint 外键名称 foreign key (外键字段) references 主表名(主表字段名) on update cascade on delete cascade;

案例

-- 外键的删除和更新行为
alter table emp add constraint fk_emp_dept_id foreign key (dept_id) references dept(id) on update cascade on delete cascade;
alter table emp add constraint fk_emp_dept_id foreign key (dept_id) references dept(id) on update set null on delete set null;

5. 多表查询

先拿一段案例展示一下表之间的外键连接

多对多 中间以外键相连

create table student_course(
	id int auto increment comment '主键' primary key,
	studentid int not null comment '学生ID',
	courseid  int not null comment '课程ID',
	constraint fk_courseid foreign key (courseid) references counse (id),
	constraint fk_studentid foreign key (studentid) references student (id)
)comment '学生课程中间表';
insert into student_course values (null,1,1),(null,1,2),(null,1,3),(null,2,2),(null,2,3),(null,3,4);

一对一 中间多创建一个表(tb_user_edu) 相连两个表

create table tb_user(
	id int auto_increment primary key comment comment '主键ID',
	name varchar(10) comment '姓名',
	age int comment '年龄',
	gender char(1) comment '1: 男 ,2: 女',
	phone char(11) comment '手机号'
)comment '用户基本信息表';

create table tb_user_edu(
	id int auto_increment primary key comment '主键ID',
	degree varchar(20) comment '学历',
	major varchar(50) comment '专业',
	primaryschool varchar(50) comment'小学'
	middleschool varchar(50) comment'中学'
	university varchar(50) comment'大学',
	userid int unique comment'用户ID',
	constraint fk_userid foreign key (userid) references tb_user(id)
)comment'用户教育信息表';

多表查询概述

  • 概述:指从多张表中查询数据
  • 笛卡尔积:笛卡尔乘积是指在数学中,两个集合A集合和B集合的所有组合情况。(在多表查询时,需要消除无效的笛卡尔积)

在这里插入图片描述

可以通过where来消除笛卡尔积

select * from emp,dept where emp.dept_id = dept.id;

多表查询可以分为

  • 连接查询
    • 内连接
    • 外连接
      • 左外连接
      • 右外连接
    • 自连接
  • 子查询

具体含义在小章节会简述


5.1 连接查询

5.1.1 内连接

内连接查询的是两张表交集的部分

#内连接查询语法
-- 隐式内连接
select 字段列表 from1,2 where 条件...-- 显式内连接
select 字段列表 from1 [inner] join2 on 连接条件...

eg:

-- 1.查询每一个员工的姓名,及关联的部门的名称(隐式内连接实现)
-- 表结构:emp,dept
-- 连接条件:emp.dept_id=dept.id
select emp.name,dept.name from emp,dept where emp.dept_id = dept.id;
select e.name,d.name from emp e , dept d where e.dept_id = d.id;


-- 2.查询每一个员工的姓名,及关联的部门的名称(显式内连接实现)---- INNER JOIN..ON//
-- 表结构:emp,dept
-- 连接条件:emp.dept_id=dept.id
select e.name,d.name from emp e inner join dept done.dept_id =d.id;
select e.name,d.name from emp e join dept d on e.dept_id = d.id;

5.1.2 外连接

#外连接查询语法
-- 左外连接
select 字段列表 from1 left [outer] join2 on 条件...;
#相当于查询表1(左表)的所有数据包含表1和表2交集部分的数据


-- 右外连接
select 字段列表 from1 right [outer] join2 on 条件...;
#相当于查询表2(右表)的所有数据包含表1和表2交集部分的数据

eg

-- 1 查询emp表的所有数据,和对应的部门信息(左外连接
-- 表结构:emp,dept
-- 连接条件:emp.dept_id=dept.id
select e.*,d.name from emp e left outer join dept d on e.dept_id = d.id;
select e.*,d.name from emp e left join dept d on e.dept_id =d.id;


-- 2 查询dept表的所有数据,和对应的员工信息(右外连接)
select d.* , e. from emp e right outer join dept d on e.dept_id = d.id;
select d.* , e. from dept d left outer join emp e on e.dept_id = d.id;

5.1.3 自连接

#自连接查询语法:
select 字段列表 from 表A 别名A join 表A 别名B on 条件...;
#自连接查询,可以是内连接查询,也可以是外连接查询

eg:

-- 1.查询员工及其所属领导的名字
-- 表结构:emp
select a.name , b.name from emp a , emp b where a.managerid = b.id;


-- 2,查询所有员工emp及其领导的名字emp,如果员工没有领导,也需要查询出来
-- 表结构:emp a,emp b
select a.name  '员工' , b.name '领导' from emp a left join emp b on a.managerid = b.id;

5.2 联合查询

对于union查询,就是把多次查询的结果合并起来,形成一个新的查询结果集

select 字段列表 from 表a ...
union [all]
select 字段列表 from 表b ...;

ps :

  • 对于联合查询的多张表的列数必须保持一致,字段类型也需要保持一致。
  • unionall会将全部的数据直接合并在一起, union会对合并之后的数据去重。

eg :

-- union all , union
-- 1.将薪资低于50的员工,和年龄大于50岁的员工全部查询出来。
select * from emp Where salary<500
union all
select * from emp where age>50;
# 查询出的结果有可能出现重复的行

select * from emp where salary< 5000
union
select * from emp where age > 50;
#去掉 all 就可以去重

5.3 子查询

5.3.1 标量子查询

标量子查询
子查询返回的结果是单个值(数字、字符串、日期等),最简单的形式,这种子查询称为标量子查询
常用的操作符:= ,<> , > , < , >= , <=

eg :

-- 标量子查询
-- 1. 查询“销售部”的所有员工信息
-- a. 查询“销售部”部门ID
select id from dept where name  = '销售部';

-- b. 根据销售部部门ID, 查询员工信息
select * from emp where dept_id = (select id from dept where name = '销售部');



-- 2. 查询在“方东白”入职之后的员工信息
-- a. 查询方东白的入职日期
select entrydate from emp where name = '方东白';

-- b.查询指定入职日期之后入职的员工信息
select * from emp where entrydate >select entrydate from emp where name = '方东白');

5.3.2 列子查询

子查询返回的结果是一列(可以是多行),这种子查询称为列子查询
常用的操作符:IN、NOT IN、ANY、SOME、ALL

操作符描述
in在指定的集合范围之内,多选一
not in不在指定的集合范围之内
any子查询返回列表中,有任意一个满足即可
some与 any 等同,使用 some 的地方都可以使用 any
all子查询返回列表的所有值都必须满足 in

eg :

-- 列子查询
-- 1. 查询“销售部”和“市场部”的所有员工信息
-- a. 查询“销售部”和“市场部”的部门ID
select id from dept where name = '销售部' or name = '市场部';
-- b. 根据部门ID,查询员工信息
select * from emp where dept_id in (select id from dept where name = '销售部' or name = '市场部');


-- 2. 查询比财务部所有工资都高的员工信息
-- a. 查询所有财务部人员工资
select id from dept where name = '财务部';
select salary from emp where dept_id =select id from dept where name = '财务部');
-- b.比财务部所有人工资都高的员工信息
select * from emp where salary > all (select salary from emp where dept_id = (select id from dept where name = '财务部'));


-- 3. 查询比研发部其中任意一人工资高的员工信息
-- a. 查询研发部所有人工资
select salary from emp where dept_id =select id from dept where name = '研发部');
-- b. 比研发部其中任意一人工资高的员工信息
select * from emp Where salary > some (select salary from emp where dept_id = (select id from dept where name '研发部'));

5.3.3 行子查询

子查询返回的结果是一行(可以是多列),这种子查询称为行子查询
常用的操作符:= , <> , in , not in

eg :

-- 1. 查询与“张无”的薪资及直属领导相同的员工信息
-- a. 查询“张无”的薪资及直属领导
select salary,managerid from emp where name = '张无'
-- b. 查询与“张无”的薪资及直属领导相同的员工信息
select from emp where (salary,managerid)=( select salary, managerid from emp where name = '张无');

5.3.4 表子查询

子查询返回的结果是多行多列,这种子查询称为表子查询
常用的操作符:IN

eg :

-- 表子查询
-- 1. 查询与“鹿客”“宋远桥”的职位和薪资相同的员工信息
-- a. 查询“鹿枝客”,“宋远桥”的职位和薪资
select job,salary from emp where name = '鹿客' or name = '宋远桥';
-- b. 查询与“鹿客”,“宋远桥”的职位和薪资相同的员工信息
select * from emp where (job,salary) in (select job,salary from emp where name = '鹿杖客' or name = '宋远桥');


-- 2. 查询入职日期是“2086-01-01之后的员工信息,及其部门信息
-- a. 入职日期是“206-1-01”之后的员工信息
select * from emp where entrydate > '2006-01-01';
-- b. 查询这部分员工,对应的部门信息
select e.*,d.* from (select from emp where entrydate > '2006-01-01')e left join dept d on e.dept_id = d.id; 

5.4 多表查询案例

-- 1. 查询员工的姓名、年龄、职位、部门信息 (隐式内连接)
-- 表:emp,dept
-- 连接条件:emp.dept_id = dept.id
select e.name , e.age , e.job , d.name from emp e , dept d where e.dept_id=d.id;

-- 2. 查询年龄小于3岁的员工的姓名、年龄、职位、部门信息(显式内连接)
-- 表:emp,dept
-- 连接条件:emp.dept_id=dept.id
select e.name , e.age , e.job , d.name from emp e inner join dept d on e.dept_id = d.id where e.age < 30;


-- 3.查询拥有员工的部门ID、部门名称
-- 表:emp,dept
-- 连接条件:emp.dept_id=dept.i
select distinct d.id , d.name from emp e , dept d where e.dept_id = d.id;


-- 4. 查询所有年龄大于4岁的员工,及其归属的部门名称;如果员工没有分配部门,也需要展示出来
-- 表:emp,dept
-- 连接条件:emp.dept_id=dept.id
-- 外连接
select e.* , d.name from emp e Left join dept d on e.dept_id = d.id where e.age > 40;


-- 5. 查询所有员工的工资等级
-- 表:emp,sagrade
-- 连接条件:emp.salary>= salgrade.losal and demp.salary <= sagrade.hisal
select e.* , s.grade , s.losal , s.hisal from emp e , salgrade s where e.salary >= s.losa and e.salary <= s.hisal;
select e.* , s.grade , s.losal , s.hisal from emp e , salgrade s where e.salary between s.losal and s.hisal;


-- 6. 查询“研发部”所有员工的信息及工资等级
-- 表:emp,salgrade,dept
-- 连接条件:emp.salary between salgrade.losal and salgrade.hisal , emp.dept_id = dept.id
-- 查询条件:dept.name= '研发部'
select e.* ,  s.grade from emp e , dept d , salgrade s where e.dept_id = d.id and (e.salary between s.losal and s.hisal)  and d.name = '研发部';


-- 7. 查询“研发部”员工的平均工资
-- 表:emp,dept
-- 连接条件: emp.dept_id = dept.id
select avg(e.salary) from emp e , dept d where e.dept_id = d.id and d.name = '研发部';


-- 8. 查询工资比“灭绝”高的员工信息
-- a. 查询“灭绝”的薪资
select salary from emp where name = '灭绝';
-- b. 查询比她工资高的员工数据
select * from emp where salary > (select salary from emp where name = '灭绝');


-- 9. 查询比平均薪资高的员工信息
-- a. 查询员工的平均薪资
select avg(salary) from emp;
-- b. 查询比平均薪资高的员工信息
select * from emp where salary > (select avg(salary) from emp);


-- 10. 查询低于本部门平均工资的员工信息
-- a. 查询指定部门平均薪资
select avg(e1.salary) from emp e1 Where e1.dept_id = 1;
select avg(e1.salary) from emp e1 where e1.dept_id = 2;
-- b. 查询低于本部门平均工资的员工信息
select * from emp e2 where e2.salary < (select avg(e1.salary) from emp e1 where e1.dept_id = e2.dept_id );


-- 11. 查询所有的部门信息,并统计部门的员工人数
select d.id , d.name , (select count(*) from emp e where e.dept_id = d.id) '人数' from dept d;
select count(*) from emp where dept_id = 1;


-- 12. 查询所有学生的选课情况,展示出学生名称,学号,课程名称
-- 表 : student , course , student_course
-- 连接条件:student.id = student_course.studentid , course.id = student_course.courseid
select s.name , s.no , c.name from student s , student_course sc , course c where s.id = sc.studentid and sc.courseid = c.id;

6. 事务

事务的四大特性(ACID)

  • 原子性(Atomicity) : 事务是不可分割的最小操作单元,要么全部成功,要么全部失败.
  • 一致性(Consistency) : 事务完成时,必须使所有的数据都保持一致状态.
  • 隔离性(Isolation) : 数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行.
  • 持久性(Durability) : 事务一旦提交或回滚,他对数据库中的数据的改变就是永久的.

6.1 事务的基本操作

#查看/设置事务提交方式
select @@autocommit;
set @@autoccommit = 0; --0是自动提交,1是手动提交,即使用commit

#提交事务
commit;

#回滚事务
rollback;

eg : 方式一

select @@autocommit;

set @@autocommit = 0--设置为手动提交

-- 转账操作(张三给李四转账1088)
-- 1.查询张三账户余额
select * from account where name = '张三';

-- 2.将张三账户余额-1080
update account set money = money - 1000 where name = '张三';

程执行报错... #手动报错

-- 3.将李四账户余额+1000
update account set money = money+1000 where name = '李四';

--提交事务
commit;

--回滚事务
rollback;

eg : 方式二

#开启事务
start transactionbegin;

#提交事务
commit;

#回滚事务
rollback;

已经设置为自动提交

-- 方式二
-- 转账操作(张三给李四转账1000
start transaction;

-- 1. 查询张三账户余额
select * from account where name = '张三';

-- 2. 将张三账户余额-18
update account set money = money - 1000 where name = '张三';

手动执行报错...

-- 3.将季四账户余额+1000
update account set money = money + 1000 where name = '李四';

-- 提交事务
commit;

--回滚事务
rollback;

6.2 并发事务问题

问题描述
脏读一个事务读到另外一个事务还没有提交的数据
不可重复读一个事务先后读取同一条记录,但两次读取的数据不同,称之为不可重复读。
幻读一个事务按照条件查询数据时,没有对应的数据行,但是在插入数据时,又发现这行数据已经存在,好像出现了 “幻影”。
  • 脏读
    B事务读取到了A事务还没有提交的数据
    在这里插入图片描述
  • 不可重复读
    事务A用同样的方法读到了不一样的数据
    在这里插入图片描述
  • 幻读
    事务A插入不进去,也读不出来,可以理解为,脏写,hhh
    在这里插入图片描述

6.3 事务的隔离级别

隔离级别不可重复读幻读
read uncommittedfalsefalsefalse
read committed (oracle 的默认)truefalsefalse
repeatable read (默认)truetruefalse
serializabletruetruetrue
#查看事务隔离级别
select @@transaction_isolation;

#是指事务隔离级别
set [session|global] transaction isolation level [read uncommitted | read committed | repeatable read | serializable ];
-- 查看事务隔离级别
select @@atransaction_isoation

-- 设置事务隔离级别
set session transaction isolation level read uncommitted ;
set session transaction isolation Level repeatable read ;

需要注意的是 : 事务隔离级别越高,数据越安全,但是性能会越低

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1077784.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

配电室管理系统:现代化电力分配的重要工具

随着科技的发展和工业化进程的加速&#xff0c;电力已经成为现代社会运行的基础。配电室作为电力供应系统的重要组成部分&#xff0c;其管理效率直接影响到人们的生产、生活。为此&#xff0c;配电室管理系统应运而生&#xff0c;这是一种集信息化、自动化、网络化于一体的电力…

实现Promise所有核心功能和方法

一直以来对Promise只是会用简单的方法&#xff0c;例如then&#xff0c;catch等&#xff0c;对于其余各种方法也只是简单了解&#xff0c;这次想要通过实现Promise来加深对Promise的使用 话不多说&#xff0c;直接开始&#xff0c;简单粗暴一步步来 一&#xff1a;了解Promise …

Go 复合类型之字典类型介绍

Go 复合类型之字典类型介绍 文章目录 Go 复合类型之字典类型介绍一、map类型介绍1.1 什么是 map 类型&#xff1f;1.2 map 类型特性 二.map 变量的声明和初始化2.1 方法一&#xff1a;使用 make 函数声明和初始化&#xff08;推荐&#xff09;2.2 方法二&#xff1a;使用复合字…

计算机网络 | 体系结构

计算机网络 | 体系结构 计算机网络 | 体系结构概念及功能计算机网络简介计算机网络的功能因特网发展阶段小结 组成与分类计算机网络的组成计算机网络的分类小结 标准化工作及相关组织速率相关性能指标速率带宽吞吐量小结 时延相关性能指标时延时延带宽积往返时延RTT利用率小结 …

【photoshop学习】用 Photoshop 做的 15 件创意事

用 Photoshop 做的 15 件创意事 每个人总是谈论 Photoshop 的无限可能。您可以使用该程序做很多事情&#xff0c;列表几乎是无穷无尽的。 嘿&#xff0c;我是卡拉&#xff01;如果您花过一些时间使用 在线ps&#xff0c;您可能见过我&#xff08;并且注意到我提到了这一点&am…

粘性文本整页滚动效果

效果展示 CSS 知识点 background 相关属性综合运用position 属性的 sticky 值运用scroll-behavior 属性运用scroll-snap-type 属性运用scroll-snap-align 属性运用 整体页面效果实现 <div class"container"><!-- 第一屏 --><div class"sec&qu…

【Linux服务端搭建及使用】

连接服务器的软件&#xff1a;mobaxterm 设置root 账号 sudo apt-get install passwd #安装passwd 设置方法 sudo passwd #设置root密码 su root #切换到root账户设置共享文件夹 一、强制删除原有环境 1.删除python rpm -qa|grep pytho…

【已解决】msvcp140.dll丢失怎样修复?msvcp140.dll重新安装的解决方法

今天我要和大家分享的是关于msvcp140.dll丢失的五种不同解决方法。我们知道&#xff0c;在运行一些软件或游戏的时候&#xff0c;经常会遇到“msvcp140.dll丢失”的问题&#xff0c;这可能会影响到我们的使用体验。那么&#xff0c;面对这个问题&#xff0c;我们应该如何应对呢…

【Python】实现excel文档中指定工作表数据的更新操作

在做数值计算时&#xff0c;个人比较习惯利用excel文档的公式做数值计算进行对比&#xff0c;检查异常&#xff0c;虽然计算量大后&#xff0c;excel计算会比较缓慢&#xff0c;但设计简单&#xff0c;易排错 但一般测试过程中使用到的数据都不是最终数值&#xff0c;会不停根据…

win1011安装MG-SOFT+MIB+Browser+v10b

文章目录 安装MG-SOFTSNMP服务配置安装MG-SOFT启动MIB-Browser以及错误解决MIB Browser使用 安装MG-SOFT win10和win11安装基本一样&#xff0c;所以参照下面的操作即可&#xff01; SNMP服务配置 打开设置&#xff0c;应用和功能&#xff0c;可选功能&#xff0c;选择添加功…

探馆天津车展 近距离感受“极致性能王”远航汽车

近年来&#xff0c;新能源汽车产业发展迅猛。得益于新能源车型在成本控制、品质、安全性等多方面的出色表现&#xff0c;消费者对新能源汽车的需求一直呈现刚性。2023年&#xff0c;虽然新能源汽车已经进入无补贴时代&#xff0c;但消费者对新能源汽车的需求依旧有增无减&#…

23年基因蓝皮书略读

2023年基因慧蓝皮书略读 1.发展环境1.1 宏观环境1.2 基因产业内涵 2 应用场景2.1 生育支持与生育健康筛查2.2 老龄化与肿瘤精准防控2.2.1 肿瘤早筛2.2.2 肿瘤伴随诊断2.2.3 MRD检测2.2.4 生物药研发及基因科技 3 产业发展3.1 产业图谱及产业链分析拟上市肿瘤检测公司上市基因企…

论文解析——AMD EPYC和Ryzen处理器系列的开创性的chiplet技术和设计

ISCA 2021 摘要 本文详细解释了推动AMD使用chiplet技术的挑战&#xff0c;产品开发的技术方案&#xff0c;以及如何将chiplet技术从单处理器扩展到多个产品系列。 正文 这些年在将SoC划分成多个die方面有一系列研究&#xff0c;MCM的概念也在不断更新&#xff0c;AMD吸收了…

超低延时直播技术演进之路-进化篇

一、概述 网络基础设施升级、音视频传输技术迭代、WebRTC 开源等因素&#xff0c;驱动音视频服务时延逐渐降低&#xff0c;使超低延时直播技术成为炙手可热的研究方向。实时音视频业务在消费互联网领域蓬勃发展&#xff0c;并逐渐向产业互联网领域加速渗透。经历了行业第一轮的…

并发、并行、同步、异步、阻塞、非阻塞

一、多核、多cpu &#xff08;一&#xff09;多核 Multicore 核是CPU最重要的部分。负责运算。核包括控制单元、运算单元、寄存器等单元。 多核就是指单个CPU中有多个核。 &#xff08;二&#xff09;多cpu Multiprocessor 多cpu就是一个系统拥有多个CPU。每个CPU可能有单个核…

JSON数据处理工具-在线工具箱网站tool.qqmu.com的使用指南

导语&#xff1a;无论是处理JSON数据、进行文本数字处理、解码加密还是使用站长工具&#xff0c;我们都希望能够找到一个功能强大、简便易用的在线平台。tool.qqmu.com作为一款瑞士军刀般的在线工具箱网站&#xff0c;满足了众多用户的需求。本文将介绍tool.qqmu.com的多项功能…

短视频矩阵系统seo源码saas开发---一手源头

一套优秀的短视频全链条获客系统&#xff0c;支持抖音获客seo排名、抖音SEO优化的系统应该如何开发&#xff0c;应该具备哪些功能&#xff1f;今天小编就跟大家分享一下我们的开发思路。 首先&#xff0c;目前公认的、抖音短视频seo优化方向&#xff0c;SaaS源码&#xff0c;系…

VIT(Vision Transformer)学习-模型理解(一)

VIT (Vision Transformer) 模型论文代码(源码)从零详细解读&#xff0c;看不懂来打我_哔哩哔哩_bilibili VIT模型架构图 1.图片切分为patch 2. patch转化为embedding 1&#xff09;将patch展平为一维长度 2&#xff09;token embedding&#xff1a;将拉平之后的序列映射…

初识 C语言文件操作

目录 前言&#xff1a; 为什么我们要使用文件&#xff1f; 什么是文件&#xff1f; 程序文件&#xff1a; 数据文件&#xff1a; 文件名&#xff1a; 文件的打开和关闭 文件指针&#xff1a; 流程&#xff1a; 文件路径&#xff1a; 文件的顺序读写&#xff1a; …