0
点赞
收藏
分享

微信扫一扫

【MySQL】基础知识总结

Android开发指南 2022-04-21 阅读 93
数据库

MySQL数据库基础知识总结


什么是数据库?
数据库是用来组织、存储和管理数据的仓库。
数据库是一种软件,组织大量的数据(一般在磁盘上),应用到数据结构。
常见的数据库有MySQL、Oracle、SQL Sever等。在这里我们只讨论MySQL。

文章目录


一、数据库操作

1.1 显示当前数据库

-- 显示当前数据库
show databases;

注意:
(1)MySQL中的sql语句绝大部分都需要带分号,个别不需要。
(2)sql中不区分大小写。
(3)可以使用其他编辑器来输入sql,这时候是有高亮和补全的,例如:VSCode。
(4)在数据库中,-- 后面是注释内容,注意之间要有一个空格。

1.2 创建数据库

-- 注意:数据库名只能由数字、字母、下划线组成,不能有其他的。
create database 数据库名;
create database 数据库名 character set utf8mb4;
-- 搭配if not exists
create database if not exists 数据库名;

说明:当我们创建数据库没有指定字符集和校验规则时,系统使用默认字符集:utf8,校验规则是:utf8_general_ci。MySQL的utf8编码不是真正的utf8,没有包含某些复杂的中文字符。MySQL真正的utf8是使用utf8mb4,建议大家都使用utf8mb4。

1.3 使用数据库

use 数据库名;-- 使用、指定数据库

1.4 删除数据库

drop database 数据库名;
-- 搭配if exists,如果存在则删除
drop database if exists 数据库名;

注意:删除操作非常危险!!工作中一定要注意!一旦删除,通过常规手段时无法找回的。


二、常用数据类型

有了数据库之后,要真正去存储组织数据,还需要数据表。创建表的时候就需要指定表的结构。表结构中就涵盖了有哪些字段,以及每个字段的类型是什么。

2.1 数值类型

在这里插入图片描述

一般不建议使用float(m,d)和double(m,d),会发生精度丢失,误差比较大,建议使用decimal(m,d)。

注意:

  1. 1字节(bytes)= 8bit。
  2. 数值类型可以指定为无符号(unsigned),表示不取负数。尽量不使用unsigned,对于int类型可能存放不下的数据,int unsigned同样可能存放不下,与其如此,还不如设计时,将int类型提升为bigint类型。

2.2 字符串类型

注意:字符串都需要使用单引号引起来,如 ‘字符串内容’ 。

2.3 日期类型

小结:
常用数据类型:
int
double(m,d)
decimal(m,d) :m指定长度,d指定小数位数。表示更精确的小数.
varchar
text
在MySQL中没有数组类型


三、表的操作

表操作之前,必须要先use数据库

3.1 创建表

-- 先指定数据库
use 数据库名;
create table [if not exists] 表名(
	字段1  数据类型  字段属性,
	字段2  数据类型  字段属性,
	......
	字段n  数据类型  字段属性
	-- 注意,最后一个字段定义时不加逗号
);


可以使用comment增加字段说明,在表结构中可以看见,如下:

-- 举例:
create table stu_test(
	id int,
	name varchar(20) comment '姓名',
	password varchar(50) comment '密码',
	age int,
	sex varchar(1),
	birthday timestamp,
	amout decimal (13,2),
	resume text
);

注意:
创建表的时候,如果表名或者列名和sql中的关键字重复了,就会报错。
解决方法:使用反引号将名字冲突的部分引起来。(键盘esc的下方)

-- 例如:
create table `create`(
	id int,
	name varchar(20)
);

3.2 删除表

drop table 表名;
-- 搭配 if exists,如果存在某表就删除
drop table if exists 表名;

注意:慎之又慎!!

3.3 查看表结构

desc 表名;-- 查看表结构

3.4 查看当前所有表

show tables;-- 查看当前所有表

四、MySQL表的增删改查(CRUD)

CRUD 即增加(Create)、查询(Retrieve)、更新(Update)、删除(Delete)四个单词的首字母缩写。


4.1 新增数据

4.1.1 全列插入

insert into 表名 values (对应的字段内容);
-- 注意:插入的字段的数目和类型需要和表结构中的要求一致。

整数可以直接插入,字符串需要带引号,对单双引号无要求。

-- 举例:
insert into student values(1,'test',98.5,'test@qq.com');

4.1.2 指定列插入

根据需要只插入其中的某几列

insert into 表名 (若干个指定列) values (对应的列数据);

注意:
(1)数目和类型都要对应;
(2)指定的列都得在表头中存在;
(3)没有被插入的列会默认被填充为null

-- 举例:
insert into student (id,name) values (1,'孙悟空');

4.1.3 一次插入多条记录

插入的时候可以一个insert语句同时插入多组数据

insert into 表名 values (对应的列数据),(对应的列数据),(对应的列数据)......

例如:

-- 举例:
insert into student (id,name) values (1,'孙悟空'),(2,'猪八戒'),(3,'沙和尚'),(4,'唐僧');

4.2 查询数据

SQL中最复杂的就是查找,有各种各样的查找方法。

4.2.1 全列查找

*是一个通配符,意思是把所有的列都查找出来。

-- 通常情况下不建议使用
select * from 表名;
-- 1.查询的列越多,意味着需要传输的数据量越大;
-- 2.可能会影响到索引的使用。(索引待后面课程讲解)

注意:
这样的查找方式仅限于在测试环境中使用,千万不能在生产环境的服务器上执行这样的SQL!!
拓展:生产环境的服务器压力本来就很大,生产环境的服务器(数据库)数据量非常多,一旦执行这样的select*操作,可能就会给生产环境的服务器造成很大负担,甚至导致服务器卡死或者宕机。生产环境的服务器如果坏了,会给用户造成恶劣影响,很可能给公司带来很大的经济损失。
在工作中,操作生产环境时,一定要非常非常谨慎!!!

4.2.2 指定列查找

 select 列名 from 表名;

4.2.3 查询字段为表达式

针对查到的列进行一定的表达式计算。

select 表达式 from 表名;

4.2.4 查询字段指定别名

select 表达式 (as) 别名 from 表名;

4.2.5 指定列去重

使用 distinct 关键字

select distinct 指定列 from 表名;

4.2.6 排序

asc 表示升序,从小到大(一般可以省略,默认升序)
desc 表示降序,从大到小,需要指定。

select 列名 from 表名 order by/表达式  asc/desc;

4.2.7 条件查询

使用 where 进行条件查询,搭配比较运算符和逻辑运算符。

select 列名 from 表名 where 条件表达式;
-- 条件为真的记录才会被最终获取到

注意:
1. where条件可以使用表达式,但不能使用别名。
2. and 的优先级高于or,在同时使用时,需要使用小括号() 包裹优先执行部分。
3. 判断是否和null相等时,要用 <=> 或者 is null,不能直接用 = 。
4. 在MySQL中如果对null进行比较、求和等操作时,结果的值也都是null,一般工作中的数据库很少会涉及null。

4.2.8 分页查询

select 列名 from 表名 limit 结果的数目;
select 列名 from 表名 limit 结果的数目 offset 起始记录的下标 ;

当写一个查询语句时,有多个条件共同控制过滤数据,应该把能过滤掉的记录多的条件写在前面。


4.3 修改数据

update 表名 set 列名 = 新的值 where 筛选条件;
  1. 可以同时指定修改多个列;
  2. 修改时也可以指定一些更复杂的表达式,如score = score+10;
  3. 修改数据时,数据不应该超出指定列的数据类型的范围。

4.4 删除数据

delete from 表名 where 筛选条件;

拓展
数据库的数据都是存到磁盘上的,如果数据特别多,超出磁盘容纳的上限,此时就无法继续写入数据了。根据数据的重要情况,决定是定期清理还是定期备份。还可以使用分布式的方法,针对数据库进行分库、分表,使用多台机器共同保存所有的数据集合。
删除操作非常危险,一旦数据被删除了,通过常规手段是无法恢复的,数据库都会支持一些丰富的“权限”控制。
例如:有些数据,只能读,不能改。
有些数据,能读能改,不能删除。


五、数据库约束

约束:数据库针对数据进行一系列的校验。如果发现插入的数据不符合约束中描述的校验规则,就会插入失败,为了更好的保证数据的正确性。

5.1 约束类型

NOT NULL : 指示某列不为空(null)。
UNIQUE :保证某列的所有行数据是不能重复的。
DEFAULT : 规定没有给列赋值时的默认值。
PRIMARY KEY (主键): NOT NULL 和 UNIQUE 的结合。确保某列(或两个列多个列的结合)有唯一标识,有助于更容易更快速地找到表中的一个特定的记录。
可以和 auto_increment 搭配,表示自增。如果表中没有任何记录,自增从1开始,否则,从上一条记录往下自增。
【注意】:
(1)如果把中间的某个数据删除之后,再次插入其他的数据,刚才删掉的自增主键的值不会被重复利用!
(2)自增要保证在有效范围内,比如int类型的自增主键,有效范围就是-21亿~+21亿,如果数据超出范围,继续自增就会出现溢出的情况。
FOREIGN KEY(外键) :保证一个表中的数据匹配另一个表中的值的参照完整性,描述两张表之间的关联关系。
外键用于关联其他表的主键或唯一键。
格式:

foreign key (字段名) references 主表()

需要指定三方面关系:
(1)指定和当前表中的哪列进行关联;
(2)指定和哪张表关联;
(3)指定和目标表中的哪一列关联。
指定后,后续插入数据时,MySQL会自动检查当前字段的值是否在另一个表的列中出现过,没有的话就会插入失败。
使用外键,会对插入操作的效率产生一定的影响,外键约束也会影响表的删除。
CHECK : 保证列中的值符合指定的条件。对于MySQL数据库,对CHECK子句进行分析,但是忽略CHECK子句。(这里不详细讲解)

举例:创建classes班级表,id 为主键:

drop table if exists classes;
create table classes (
	id int primary key auto_increment,
	name varchar(20),
	`desc` varchar(100)-- 字段和关键字同名,使用反引号``来标识。
);

创建学生表student,一个学生对应一个班级,一个班级对应多个学生。使用id作为主键,classes_id 作为外键,关联班级表id :

drop table if exists student;
create table student (
	-- id int not null, 使用主键就可以省略not null
	id int primary key auto_increment,-- 主键约束
	-- 主键时not null 和 unique 的结合
	sn int unique,
	name varchar(20) default 'unknown',-- 设置默认值
	qq_mail varchar(20),
	classes_id int,
	foreign key (classes_id) references classes(id)-- 指定外键
);


六、表的设计

聚焦于设计表时的实体间的关系。
三大范式:一对一、一对多、多对多。
一对一关系:一个人只能有一个身份证,一个身份证只能被一个人拥有。
一对多关系:一个学生只能在一个班级,一个班级可以有多个学生。
一对多关系,需要通过外键来组织。
比如:
在这里插入图片描述
注意:不可以当成是一个数组,数组中的每一个元素表示一个学生信息。MySQL中没有数组类型。

多对多关系:一个学生可以有多门课程,一门课程也可以被多个学生选择。
多对多关系很复杂,需要引入中间表来解决这个问题。


七、查询

7.1 聚合查询

把查询结果中的若干行数据合并到一起,一般需要搭配MySQL中的一些内置“函数”。

7.1.1 聚合函数

常见的聚合函数有:
count:计算结果的行数,不包含空行。

count([distinct] expr)  -- 返回查询的数据的数量(非null)
-- 注意:count和(之间没有空格,否则会被当成列名!

sum:返回查询到的数据的总和,不是数字没有意义。

sum([distinct] expr)

avg:返回查询到的数据的平均值,不是数字没有意义。

avg([distinct] expr)

max:返回查询到的数据的最大值,不是数字没有意义。

max([distinct] expr)

min:返回查询到的数据的最小值,不是数字没有意义。

min([distinct] expr)

7.2 分组查询

7.2.1 group by 子句

select 中使用group by子句可以对指定列进行分组查询,类似于hadoop中的map reduce操作中的reduce。
需要满足:使用 group by进行分组查询时,select 指定的字段必须是“分组依据字段”,其他字段若想出现在select 中则必须包含在聚合函数中。

select1,sum(2),...from 表名 group by1,2;
-- 举例:查询每个角色的最高工资、最低工资和平均工资
select role,max(salary),min(salary),avg(salary) from emp group by role;

7.2.2 having

使用group by子句进行分组后,需要对分组结果再进行条件过滤时,不能使用where语句,而需要用having。

-- 显示平均工资低于1500的角色和它的平均工资
select role,max(salary),min(salary),avg(salary) from emp group by role having avg(salary)<1500;

小结:having与group by的区别:
having是针对group by 之后的结果进行筛选,where是针对原始表中的每条记录都进行筛选。

7.3 联合查询

这部分在MySQL中非常重要也非常难理解,多多练习!
在实际开发中,数据往往来自不同的表,所以需要多表联合查询。多表查询是对多张表的数据取笛卡尔积。
【注意】:关联查询可以对关联表使用别名。

7.3.1 内连接

内连接也称为等值连接,返回两张表都满足条件的部分。inner join 等价于 join。

-- 语法:
select 字段 from 表A 别名A [inner] join 表B 别名B on 连接条件 and 其他条件;

select 字段 from 表A 别名A,表B 别名B where 连接条件 and 其他条件;

举例:

--查询许仙同学的成绩
select sco.score from student stu inner join score sco on stu.id=sco.student_id
and stu.name='许仙';
-- 或者
select sco.score from student stu, score sco where stu.id=sco.student_id and
stu.name='许仙';

7.3.2 外连接

外连接分为左外连接(left join)和右外连接(right join)。
如果联合查询,左侧的表完全显示我们就说是左外连接;右侧的表完全显示我们就说是右外连接。

-- 左外连接,表A完全显示
-- 取左边的表的全部,右边的表按条件,符合的显示,不符合则显示null
select 字段名 from 表名A left join 表名B on 连接条件;
-- 右外连接,表B完全显示
-- 取右边的表的全部,左边的表按条件,符合的显示,不符合则显示null
select 字段名 from 表名A right join 表名B on 连接条件;

7.3.3 自连接

自连接是指在同一张表连接自身进行查询。本质上相当于同一列中的两行记录转换成不同列的同一行记录。

-- 找出所有计算机原理比Java成绩高的同学id
-- (1)先找到Java和计算机原理的课程id
select * from course where name = 'java';
select * from course where name = '计算机原理';
-- (2)按照课程id在分数表中筛选数据
select 
	-- (a)针对score表自身进行笛卡尔积
	s1.student_id,s1.score,s1.course_id,s2.student_id,s2.score,s2.course_id 
from 
 	score s1,
 	score s2 
where 
	--(b)加上学生id的限制
 	s1.student_id = s2.student_id 
	-- (c)加上课程id的限制 
 	and s1.course_id = 3 
 	and s2.course_id = 1 
 	-- (d)按照分数大小进行比较
 	and s1.score > s2.score;

7.3.4 子查询

子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询。
分为单行子查询和多行子查询。
单行子查询:返回一行记录的子查询。

-- 举例:查询与“不想毕业” 同学的同班同学
select * from student where classes_id=(select classes_id from student where
name='不想毕业');

多行子查询:返回多行记录的子查询。
(1)借助 in 的方式来查询
先执行子查询,把子查询的结果保存到内存中,再进行主查询,再结合刚才子查询的结果来筛选最终结果。
注意:多行子查询时要使用 in 而不是 = 。

-- 举例:查询“语文“或者”英文“课程对应的成绩
select * from score where course_id in (select id from course where name = '语文' or name = '英文' );

(2)借助exists方式来查询
先执行主查询,再触发子查询。

-- 举例:查询“语文“或者”英文“课程对应的成绩
select * from score where exists (select score.course_id from course where (name = '语文' or name = '英文') and course_id = score.course_id);

针对主表中的每个查询记录,都会再触发一次子查询。执行很多次,相当于用时间来换空间。

注意
如果子表查询的结果集合比较小,就使用in (更推荐使用);如果子表查询的结果集合比较大,而主表的集合小,就使用exists。

7.3.5 合并查询

在实际应用中,为了合并多个select的执行结果,可以使用集合操作符 union,union all。使用union
和union all 时,前后查询的结果集中,字段需要一致。
union:该操作符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中的重复行。
union all:该操作符用于取得两个结果集的并集。当使用该操作符时,不会去掉结果集中的重复行。

-- 举例:查询id  < 3 并且名字为 '英文'的课程。
-- 普通查询
select * from course where id <3 or name = '英文';
--  使用union 关键字
select * from course where id < 3 union select * from course where name = '英文';
-- 如果两个查询结果中存在相同的记录,就会只保留一个
-- 如果不想去重,可以使用union all即可。

拓展:SQL的特点,不需要用户来指定一步一步该如何执行,只要告诉数据库,最终想要啥数据即可。像C/Java这种编程语言则需要告诉计算机每一步都该如何执行。

小结: MySQL基础知识整体都比较简单,联合查询部分略有难度,需要多加练习。推荐刷牛客题库里的SQL必知必会。面试常考的索引和事务部分后续会讲解。

举报

相关推荐

0 条评论