MySQL数据管理

MySQL数据管理

1. 外键(了解)

https://images.cnblogs.com/cnblogs_com/wang-sky/1815470/o_200811083005%E5%A4%96%E9%94%AE.png

1. 方式1

在创建表的时候,增加约束(麻烦,比较复杂)

create table `grade` (
  `gradeId` int(10) not null auto_increment comment '年级id',
  `gradename` varchar(50) not null comment '年级名称',
  primary key (`gradeId`)
)engine=innodb default charset=utf8

drop table if exists student

/*学生表的gradeId字段要去引用年级表的gradeId
  定义外键key
  给这个外键添加约束(执行引用)
  fk = foreign key的简写
 */
create table if not exists `student` (
  `id` int (4) not null auto_increment comment '学号',
  `name` varchar (30) not null default '匿名' comment '姓名',
  `pwd` varchar (20) not null default '123456' comment '密码',
  `sex` varchar (2) not null default '女' comment '性别',
  `birthdat` datetime default null comment '出生日期',
  `gradeId` int(10) not null comment '学生的年级',
  `address` varchar (100) default null comment '家庭住址',
  `email` varchar (50) default null comment '邮箱',
  primary key (`id`),
  key `fk_gradeId` (`gradeId`),
  constraint `fk_gradeId` foreign key (`gradeId`) references `grade` (`gradeId`) 
) engine innodb default charset = utf8 

删除有外键关系的表的时候,必须先删除应用别人的表(从表),再删除被应用的表(主表)

2. 方式2

创建表成功后,添加外键约束

/*创建表的时候,没有外键关系
  alter table 表名
  add constraint 约束名 foreign key(作为外键的列) references 引用到的表(引用到的表中的对应的列);
*/
create table if not exists `student` (
  `id` int (4) not null auto_increment comment '学号',
  `name` varchar (30) not null default '匿名' comment '姓名',
  `pwd` varchar (20) not null default '123456' comment '密码',
  `sex` varchar (2) not null default '女' comment '性别',
  `birthdat` datetime default null comment '出生日期',
  `gradeId` int(10) not null comment '学生的年级',
  `address` varchar (100) default null comment '家庭住址',
  `email` varchar (50) default null comment '邮箱',
  primary key (`id`)
) engine innodb default charset = utf8 

alter table `student`
add constraint `fk_gradeId` foreign key(`gradeId`) references `grade`(`gradeId`);

以上的操作都是物理外键,数据库级别的外键,不建议使用!(避免数据库过多造成困扰,这里了解即可)

最佳实现

  • 数据库就是单纯的表,只用来存数据,只有行(数据)和列(字段)

  • 我们想使用多张表的数据,想使用外键(程序去实现)

2. DML语言(全部记住)

数据库意义:数据存储,数据管理

DML语言:数据操作语言

  • insert
  • update
  • delete

1. 添加

insert

/*插入语句(添加)
insert into 表名([字段1,字段2,字段3])values('值1'),('值2'),('值3'),......
*/
insert into `grade`(`gradename`) values('大四')

/*由于主键自增,我们可以省略主键
  如果不写表的字段,它就会一一匹配
  一般写插入语句,我们一定要数据和字段一一对应
*/

/*插入多个字段
  values后面的字段用()包裹,并用,隔开
*/
insert into `grade`(`gradename`) 
values('大二'),('大一')

insert into `student`(`name`) values('张三')

insert into `student`(`name`,`pwd`,`sex`) values('张三','aaaaaa','男')

insert into `student`(`name`,`pwd`,`sex`) 
values('李四','bbbbbb','男'),('王五','cccccc','男')

语法

insert into 表名([字段1,字段2,字段3])values('值1'),('值2'),('值3'),......

注意事项

  1. 字段和字段之间使用英文逗号隔开
  2. 字段是可以省略的,但是后面的值必须一一对应,不能少
  3. 可以同时插入多条数据,values后面的值需要使用(),(),...隔开

2. 修改

update

/*修改学生的名字
*/
update `student` set `name`='wang' where id = 1
/*不指定条件的情况下,会改动所有表!
*/
update `student` set `name`='wang'
/*修改多个属性,用逗号隔开*/
update `student` set `name` = 'wang', `email` = 'xxxxx@qq.com' where id = 1
/*通过多个条件,定位数据*/
update `student` set `name` = '这是一个名字' where `name` = 'wang' or `sex` = '女'

语法

update 表名 set column_name = value, [column_name = value,...] where [条件]		--column列字段

条件:where子句 运算符

操作符 含义 范围 结果
= 等于 5=6 false
<>或!= 不等于 5<>6 true
> 大于 5>6 false
< 小于 5<6 true
<= 小于等于 5<=6 true
>= 大于等于 5>=6 false
between...and... 在某个范围内,闭合区间 [2,5]
and &&和 5>1 and 1>2 false
or ||或 5>1 or 1>2 true

注意:

  • column_name 是数据库的列,尽量带上``
  • 条件,筛选的条件,如果没有指定,则会修改所有的列
  • value可以是一个具体的值,也可以是一个变量

3. 删除

1. delete命令

语法

delete from 表名 [where 条件]

/*删除数据(避免这样写,会全部删除)*/
delete from `student`

/*删除指定数据*/
delete from `student` where id = 1

2. truncate命令

作用:完全清空一个数据库表,表的索引和约束条件不会变!

/*清空student表*/
truncate `student`

3. delete和truncate的区别

  • 相同点:都能删除数据,都不会删除表结构
  • 不同点:
    • truncate 能重新设置自增列,计数器会归零
    • truncate 不会影响事务

4. delete删除的问题

重启数据库,现象:

  • INNODB:自增列会从1开始(数据存在内存当中,断电即失)
  • MYISAM:继续从上一个自增量开始(数据存在文件中,不会丢失)

3. DQL语言(最重点)

查询数据

1.DQL

Data Query Language:数据查询语言

  • 所有的查询操作都用它 Select
  • 简单的查询,复杂的查询它都能做
  • 数据库最核心的语言,最重要的语句
  • 使用频率最高的语言

select完整的语法

select [all | distinct]
{* | table.* | [table.field1[as alias1][,table.field2[as alias]][,...]]}
from table_name [as table_alias]
	[left | right | inner join table_name2]	-- 联合查询
	[where ...]	-- 等值查询,指定结果需要满足的条件
	[group by ...]	-- 指定结果按照哪几个字段来分组
	[having]	-- 过滤分组的记录必须满足的次要条件
	[order by ...]	-- 排序,指定查询记录按照一个或者多个条件排序
	[limit {[offset,]row_count | row_countoffset offsets}];	-- 分页,指定查询的记录从哪条至哪条

注意:[ ]代表可选的,{ }代表必选的

2. 指定查询字段

-- 查询全部的学生  select 字段 from 表名
select * from `student`

-- 查询指定字段
select `studentno`, `studentname` from `student`

-- 别名,给结果起一个名字  as
-- 可以给字段起别名,也可以给表起别名
select `studentno` as 学号, `studentname` as 学生姓名 from `student` as s

-- 函数 concat(a,b)
-- 作用:将多个字符串合连接为一个字符串
select concat ('姓名:',`studentname`) as 新名字 from `student`

语法

select 字段1,... from 表

有的时候,列的名字不是那么的见名知意,此时我们可以起别名 用as

字段名 as 别名 
表名 as 别名

1. 去重

-- 查询一下有哪些同学参加了考试(有成绩)
select * from `result`	-- 查询全部的考试成绩
-- 查询有哪些同学参加了考试
select `studentno` from `result`
-- 发现重复数据,去重
select distinct `studentno` from `result`

作用:去除select查询出来的结果中重复的数据,重复的数据只显示一条

2. 数据库的列(表达式)

-- 查询系统版本(函数)
select version()
-- 用来计算(表达式)
select 100*3-1 as 计算结果
-- 查询自增的步长(变量)
select @@auto_increment_increment

-- 学生考试成绩+1分查看
select `studentno`,`studentresult`+1 as 提分后 from result

数据库中的表达式:文本值,列,Null,函数,计算表达式,系统变量...

语法

select 表达式 from 表

3. where条件子句

作用:检索数据中符合条件的值

搜索的条件由一个或多个表达式组成,返回结果为布尔值

1. 逻辑运算符

运算符 语法 结果描述
and && a and b a&&b 逻辑与
or || a or b a||b 逻辑或
not ! not a !a 逻辑非

尽量使用英文字母

-- ==================  where ===================
select `studentno`,`studentresult` from result

-- 查询考试成绩在95~100分之间的
select `studentno`,`studentresult` from result
where `studentresult` >=95 and `studentresult` <=100

-- 模糊查询(区间)
select `studentno`,`studentresult` from result
where `studentresult` between 95 and 100

-- 除了1000号学生之外的同学的成绩 not !
-- 注意not的位置!
-- 不加not:where `studentno`=1000,因此not放在 where之后对取值取非
select `studentno`,`studentresult` from result
where not `studentno`=1000

select `studentno`,`studentresult` from result
where `studentno` != 1000

2. 模糊查询

比较运算符

运算符 语法 描述
is null a is null 如果操作符为null,则结果为true
is not null a is not null 如果操作符为not null,则结果为true
between...and... a between b and c 若a在b和c之间,则结果为true
like a like b SQL匹配,如果a匹配b,则结果为true(可以使用通配符)
in a in (a1,a2,a3,...) 假设a在a1,或者a2...其中的某一个值中,结果为true(不能使用通配符)
-- ==================  模糊查询  ===================

-- ==================  like  ===================
-- 查询姓张的同学
-- like结合 %(代表0到任意个字符) _(一个字符)
select `studentno`,`studentname` from `student`
where `studentname` like '张%'

-- 查询姓张的同学,名字后面只有一个字的
select `studentno`,`studentname` from `student`
where `studentname` like '张_'

-- 查询姓张的同学,名字后面只有两个个字的
select `studentno`,`studentname` from `student`
where `studentname` like '张__'

-- 查询名字中有伟的同学 %伟%
select `studentno`,`studentname` from `student`
where `studentname` like '%伟%'

-- ==================  in  ===================
-- in是具体的一个或多个值,不可以用通配符
-- 查询1000,1001号学员信息
select `studentno`,`studentname` from `student`
where `studentno` in (1000,1001)

-- 查询在北京的学生
select `studentno`,`studentname` from `student`
where `address` in ('北京朝阳')

-- ==================  null	not null  ===================
-- 查询地址为空的学生 null或者''
select `studentno`,`studentname` from `student`
where `address`='' or `address` is null

-- 查询有出生日期的同学=不为空
select `studentno`,`studentname` from `student`
where `borndate` is not null

-- 查询没有出生日期的同学=为空
select `studentno`,`studentname` from `student`
where `borndate` is null

4. 联表查询

1. join对比

在这里插入图片描述

-- ==================  联表查询 join  ===================
-- 查询参加了考试的同学(学号,学号,科目编号,分数)
select * from student
select * from result

/*思路
1.分析需求,分析查询的字段来自哪些表(超过一张表采用连接查询)
2.确定使用哪种连接查询?
  确定交叉点(这两个表中哪个数据是相同的)
 判断的条件:学生表中的studentno = 成绩表studentno
 表的别名.字段:表示要查询的字段来源于哪个表
 */
 
select s.`studentno`,`studentname`,`subjectno`,`studentresult`
from `student` as s
inner join `result` as r
on s.`studentno` = r.`studentno`
 
-- Right Join
select s.`studentno`,`studentname`,`subjectno`,`studentresult`
from `student` as s
right join `result` as r
on s.`studentno` = r.`studentno`

-- Left Join
select s.`studentno`,`studentname`,`subjectno`,`studentresult`
from `student` as s
left join `result` as r
on s.`studentno` = r.`studentno`

-- 查询缺考的同学
select s.`studentno`,`studentname`,`subjectno`,`studentresult`
from `student` as s
left join `result` as r
on s.`studentno` = r.`studentno`
where `studentresult` is null
操作 描述
inner join 如果表中至少有一个匹配,就返回行
left join 会从左表中返回所有的值,即使右表中没有匹配
right join 会从右表中返回所有的值,即使左表中没有匹配

join on 和where

join (连接的表) on (判断的条件)	连接查询(多张表)

where 等值查询(一张表)

查询多张表

-- 查询了参加考试的同学信息:学号,学生姓名,科目名称,分数
/*思路
1.分析需求,分析查询的字段来自哪些表:student,result,subject
2.确定使用哪种连接查询?
  确定交叉点(这两个表中哪个数据是相同的)
  左表为学生表,右表为成绩表时,使用右连,这样可以将所有参加了考试的学生number输出
  on条件为学号相等,即可筛选出参加了考试的学生
  查询科目,将结果表与科目表inner join,on的条件为相同的subjectno,这样就能查出对应的subjectname
 判断的条件:学生表中的studentno = 成绩表studentno
 表的别名.字段:表示要查询的字段来源于哪个表
 */
 select s.`studentno`,`studentname`,`subjectname`,`studentresult`
 from `student` as s
 right join `result` as r
 on r.`studentno`=s.`studentno`
 inner join `subject` as sub
 on sub.`subjectno`=r.`subjectno`
 
 /*
我要查询哪些数据  select ...
从哪几个表中查  from 表 XXX join 连接的报表 on 交叉条件
假设存在多张表查询,慢慢来,先查询两张表然后再慢慢增加
a left join b on XXX	:以a表位基准(左连接)
a right join b on XXX	:以b表位基准(右连接)
*/

2. 自连接

自己的表和自己的表连接,核心:一张表拆为两张一样的表即可

父类

categoryId categoryName
2 信息技术
3 软件开发
5 美术设计

子类

pid categoryId categoryName
3 4 数据库
2 8 办公技术
3 6 web开发
5 7 ps技术

操作:查询父类对应的子类关系

父类 子类
信息技术 办公信息
软件开发 数据库
软件开发 web开发
美术设计 ps技术
-- 查询父子信息
select a.`categoryname` as '父栏目',b.`categoryname` as '子栏目'
-- 将一张表看为两个一模一样的表
from `category` as a,`category` as b
where a.`categoryid`=b.`pid`

5. 分页和排序

1. 排序

-- ================  排序 order by  ===============
-- 排序:升序 ASC,降序 DESC
-- 语法:order by 通过哪个字段排序,怎么排
-- 查询的结果根据 成绩降序 排序
select s.studentno,studentname,subjectname,studentresult
from student as s
inner join result as r
on s.studentno = r.studentno
inner join `subject` sub
on r.subjectno = sub.subjectno
where sub.subjectname = '高等数学-4'
-- 对成绩进行降序排序
order by studentresult desc

2. 分页

-- ================  分页 limit  ===============
-- 100万
-- 为什么要分页?
-- 缓解数据库压力,给人的体验更好

-- 分页,每页只显示五条数据
-- 语法:limit 起始值,页面的大小
-- limit 0,5	1~5条数据
-- limit 1,5	2~6条数据
select s.studentno,studentname,subjectname,studentresult
from student as s
inner join result as r
on s.studentno = r.studentno
inner join `subject` sub
on r.subjectno = sub.subjectno
where sub.subjectname = '高等数学-4'
order by studentresult desc
limit 0,1

-- 第一页	limit 0,5
-- 第二页	limit 5,5
-- 第三页	limit 10,5

-- 第n页	limit (n-1) * pageSize, pageSize
-- pageSize:页面大小
-- (n-1) * pageSize起始值
-- n:当前页
-- 数据总数/页面大小 = 总页数(向上取整,有余数时总页数+1)

语法

-- 语法:limit 起始值,页面的大小

6. 子查询

where (这个值是计算出来的)

本质:在where语句中嵌套一个子查询语句

-- =========================== where ======================
-- 1.查询 高等数学-4 的所有考试结果(学号,科目,成绩),降序排列
-- 方式1:使用连接查询
select `studentno`,`subjectname`,`studentresult`
from `result` as r
inner join `subject` as sub
on r.`subjectno` = sub.`subjectno`
where `subjectname`='高等数学-4'
order by `studentresult` desc

-- 方式二:使用子查询(由里及外)
select `studentno`,`subjectno`,`studentresult`
from `result`
where `subjectno`=(
	select `subjectno` from `subject` 
	where `subjectname`='高等数学-4'
)
order by studentresult desc

-- 分数不小于80分的学生的学号和姓名
select distinct s.`studentno`,`studentname`
from `student` as s
inner join `result` as r
on r.`studentno`=s.`studentno`
where r.`studentresult` >= 80

-- 在这个基础上增加一个科目,高等数学-2
select distinct s.`studentno`,`studentname`
from `student` as s
inner join `result` as r
on r.`studentno`=s.`studentno`
where r.`studentresult` >= 80 and `subjectno`=(
	select `subjectno` from `subject`
	where `subjectname`='高等数学-2'
)

-- 查询课程为 高等数学-2 且分数不小于 80 的同学的学号和姓名
-- 由里及外
select `studentno`,`studentname`
from `student` where `studentno` in (
	select `studentno` from `result`
	where `studentresult` >= 80 and `subjectno` = (
		select `subjectno` from `subject`
		where `subjectname` = '高等数学-2'
	)
)

7. 分组和过滤

分组的语法

group by 用于分组的字段

过滤的语法

having 过滤的条件
-- 注意:having 位于 group by之后!
-- 查询不同课程的平均分,最高分,最低分,平均分大于80
-- 核心:根据不同的课程分组
select `subjectname` as 科目,avg(`studentresult`) as 平均分,max(`studentresult`) as 最高分,min(`studentresult`) as 最低分
from `result` as r
inner join `subject` as sub
on r.`subjectno` = sub.`subjectno`
-- 通过什么字段来分组
group by r.`subjectno`
-- 利用having对分组后的结果进行过滤(此处不能用where是因为where不支持聚合函数),可以使用别名
having 平均分 >= 80

4. MySQL函数

官网:https://dev.mysql.com/doc/refman/5.6/en/sql-function-reference.html

1. 常用函数

-- ========================  常用函数  ==========================
-- 数学运算
select abs(-8)		-- 绝对值
select ceiling(9.4)	-- 向上取整
select floor(9.4)	-- 向下取整
select rand()		-- 返回一个0~1之间的随机数
select sign(-9)		-- 判断一个数的符号 0返回0,负数返回-1,正数返回1

-- 字符串函数
select char_length('这是一段字符串')	-- 字符串长度
select concat('这','是','一句话')	-- 拼接字符串
select insert('替换失败',3,2,'成功')	-- 查询,从某个位置开始替换某个长度的字符串,此处的开始位置从1开始计算
select lower('ABCdefg')			-- 转小写字母
select upper('ABCdefg')			-- 转大写字母
select instr('blue_sky','e')		-- 返回第一次出现的子串的索引
select replace('这是原来的字符串','原来','替换后')	-- 替换出现的指定字符串
select substr('这是原来的字符串',4,2)	-- 返回指定的子字符串(源字符串,截取的位置,截取的长度)
select reverse('这是原来的字符串')	-- 反转字符串

-- 查询姓 将姓赵的同学的姓替换为兆
select replace(`studentname`,'赵','兆') from `student`
where `studentname` like '赵%'

-- 时间和日期函数(重要)
select current_date()		-- 获取当前日期
select curdate()		-- 获取当前日期
select now()			-- 获取当前的时间
select localtime()		-- 获取本地时间
select sysdate()		-- 获取系统时间

select year(now())
select month(now())
select day(now())
select hour(now())
select minute(now())
select second(now())

-- 系统
select system_user()		-- 获取系统的用户
select user()			-- 获取系统的用户
select version()		-- 获取系统的版本

2. 聚合函数(常用)

函数名称 描述
count() 计数
sum() 求和
avg() 平均值
max() 最大值
min() 最小值
...
-- ======================  聚合函数  ====================
-- 都能够统计 表中的数据(想查询表中有多少个记录,就用count())
select count(`studentname`) from `student`	-- count(字段),会忽略所有的null值

select count(*) from `student` 			-- count(*),不会忽略null值,本质:计算行数
select count(1) from `student`			-- count(1),不会忽略null值,本质:计算行数

select sum(`studentresult`) as 总和 from `result`
select avg(`studentresult`) as 平均分 from `result`
select max(`studentresult`) as 最高分 from `result`
select min(`studentresult`) as 最低分 from `result`

3. 数据库级别的MD5加密(扩展)

什么是MD5?

主要是增强算法复杂度和不可逆性

MD5不可逆,具体的值MD5是一样的

MD5破解网站的原理:背后有一个字典,MD5加密后的值 加密前的值

-- ====================  测试MD5 加密  ====================
create table `testMD5` (
  `id` int(4) not null,
  `name` varchar(20) not null,
  `pwd` varchar(50) not null,
  primary key(`id`)
)engine=innodb default charset=utf8

-- 明文密码
insert into `testMD5` (`id`,`name`,`pwd`) values
(1,'张三','123456'),
(2,'李四','123456'),
(3,'王五','123456')

-- 加密全部的密码,使用函数md5()
update `testMD5` set pwd=md5(pwd)

-- 插入的时候加密
insert into `testMD5` (`id`,`name`,`pwd`) values
(4,'小明',md5('123456'))

-- 如何校验:将用户传递进来的密码进行MD5加密,然后比对加密后的值
select * from `testMD5` where `name` = '小明' and pwd = md5('123456')
原文地址:https://www.cnblogs.com/wang-sky/p/13496752.html