数据库DataBase(DB),本质就是一个存放数据的系统。
最主要的就是对表的操作(如创建、删除表),和对数据的操作(如对数据的增删改查)。
数据库的三大范式
所谓三大范式,就是设计数据库的原则
- 第一范式:列不可拆分,每一列的数据项都是原子的,也就是说单一字段不能放集合、数组等。
- 第二范式:一张表只做一件事,所有的属性都完全依赖于主键,这条主要是针对联合主键的,也就是说表中不能存在某一项只依赖主键的一部分。
- 第三范式:拆分表,添加外键建立联系。表中不能存在依赖的传递,比如员工信息表出现公司电话,公司电话依赖于公司而不是员工。它能避免表中数据冗余。
- 但是在现有的程序设计中认为第三范式是可以不遵守的,也就是通过添加冗余字段,来减少多表联查或计算,我们称为反三范式。
层次结构
数据库管理系统的层次:
软件 --> 数据库 --> 数据表 --> 数据记录
平时所讲的MySQL数据库其实是软件层级,而非数据库层级,真正数据库层次为项目层级,一个项目需要多个数据表。
SQL
SQL:操作关系型数据库的编程语言,定义操作 所有关系型数据库 的统一标准。
-
通用语法
- SQL语句可以单行或多行书写,以分号结尾。
- SQL语句可以使用空格/缩进来增强语句的可读性。
- MySQL数据库的SQL语句不区分大小写。
- 注释:单行注释:-- 注释内容 或 # 注释内容
-
SQL分类
- DDL:数据定义语言,用来定义数据库对象(数据库,表,字段),也就是对数据库和表进行操作。
- DML:数据操作语言,对数据库表中的数据进行增删改。
- DQL:数据查询语言,用来查询数据库中表的记录
- DCL:数据控制语言,用来创建数据库用户、控制数据库的访问权限。
- TCL:事务控制语言,用于控制数据库的事务操作
MySQL操作
-
DDL
数据库和数据表的操作,增删查都用的是 creat, drop, show
- 数据库操作
连接
mysql -u用户名 -p密码 [-h数据库服务器ip地址 -P端口号]
操作
以下在命令窗口中运行。也可在idea中进行,其中database,可以替换成 schema
--创建数据库 create database [ if not exists ] 数据库名; --查询所有数据库 show databases; --删除数据库 drop database [ if exists ] 数据库名; --进入或切换数据库 use 数据库名; --查询当前数据库 select database();
- 数据表操作
--查询表 show tables; --查询当前数据库中所有表 desc 表名; --查询表结构 show create table 表名; --查询建表的sql语句 --创建表 create table 表名( 字段1 字段类型(字段长度) [ comment 字段1注释 ], -- 不是分号 ...... 字段n 字段类型(字段长度) [ comment 字段n注释 ] -- 最后一列后面没有,号 ) [ comment 表注释 ] ; --删除表 drop table [ if exists ] 表名; --修改表 alter table 表名 add 字段名 类型(长度) [comment 注释] [约束]; --添加字段 alter table 表名 modify 字段名 新数据类型(长度); --修改字段类型 alter table 表名 change 旧字段名 新字段名 类型 (长度) [comment 注释] [约束]; --修改字段名和字段类型 alter table 表名 drop column 字段名; --删除字段 rename table 表名 to 新表名; --修改表名
修改表图形化
字段约束
数据类型
-
**DML**
对数据的增删改 insert, delete, update
- 数据操作
-- 添加数据 insert into 表名 (字段名1, 字段名2) values (值1, 值2); -- 修改数据 update 表名 set 字段名1 = 值1, 字段名2 = 值2, ....[ where 条件 ]; -- 删除数据 delete from 表名 [ where 条件 ];
注:
- 添加数据时,字段名和值需要用小括号
- 修改数据时,如果没有where条件,则是修改整张表数据
- 删除数据时,如果没有where条件,则是删除整张表所有数据,但不删表
-
**DQL**
对数据的查询,在数据操作业务中占比最大 select
- 数据查询操作
-- 基本查询 select * from 表名; --不建议 select 字段1 [as 别名1], 字段2 [as 别名2] from 表名; -- 去除重复记录 select distinct 字段列表 from 表名;
-- 查询 select 字段列表 from 表名 [where 条件列表] -- 条件 [group by 分组字段名] [having 分组后过滤条件] -- 分组 [order by 字段1 排序方式1, 字段2 排序方式2 …] -- 排序 [limit 起始索引, 查询记录数]; --分页
条件运算符(条件列表中使用)
聚合函数(一般分组后使用函数运算)
注:null值不参与所有聚合函数运算。一般用于分组之后的运算。分组之后,查询的字段一般为 分组的字段 和 聚合函数(根据函数计算的每组结果),查询其他字段无任何意义。
排序方式
ASC:升序(默认值) DESC:降序
注:如果是多字段排序,当第一个字段值相同时,才会根据第二个字段进行排序。
MySQL多表间关系
- 一对一:用户 与 身份证信息 的关系
- 一对多:班级(一)和学生(多)的关系。一为主表,多为从表。从表中新建的这一列为外键列,指向主表的主键列。目的是为了建立当前表和其他表的关联关系,一张表中,允许有多个外键列。
- 多对多 :学生和课程的关系,两者都可为多的一方。添加中间表,作为两张表的从表,建立联系,因此其本质上就是两个一对多拼接而成。
这种能表示表间关系的数据库称为关系型数据库
-
外键约束
-- 创建表时指定 create table 表名( 字段名 数据类型, ... [constraint] [外键名称] foreign key (外键字段名) references 主表 (字段名) ); -- 建完表后,添加外键 alter table 表名 add constraint 外键名称 foreign key (外键字段名) references 主表(字段名);
如果没有外键,删除班级一条数据,而学生有的在这个班级,那数据就出现不完整、不一致问题。添加外键后,就无法如此删除。但加过多外键,容易死锁,效率低,因此可以不加外键,而在代码逻辑上解决,也就是逻辑外键。
-
多表查询
分为内连接和外连接,显式内连接和外连接,都避免了笛卡尔积,隐式内连接会先做笛卡尔积,也就是将左表中的每一条数据分别去连接右表中的每一条数据,总数据量为两表相乘(数据量大且无用)。
-- 隐式内连接 select 字段列表 from 左表 , 右表 where 条件 ...; -- 显示内连接 select 字段列表 from 左表 [ inner ] join 右表 on 连接条件 ...; -- 左外连接 -- 首先要显示出左表的全部,然后使用连接条件匹配右表,能匹配中的就显示,匹配不中的显示为null select 字段列表 from 左表 left [ outer ] join 右表 on 连接条件; -- 右外连接 select 字段列表 from 左表 right [ outer ] join 右表 on 连接条件; -- 子查询(嵌套查询) select 字段列表 from 表 where 字段名 = (子查询); select 字段列表 from 表 where 字段名 in (子查询); select 字段列表 from (子查询) as 临时表 join 表 on 条件;
-
事务
事务是一组操作的集合,它是一个不可分割的工作单位。 单个事务中的所有操作,要么同时成功,要么同时失败。
-- 开启事务 start transaction; / begin; -- 提交事务 commit; -- 回滚事务 rollback;
四大特性
- 原子性:不可分割的最小单元,要么同时成功,要么同时失败。
- 一致性:执行前后,数据库的状态一致,不会出现不完整的情况。如转账前后,无论中途是否发生错误,两个账户中的总额是不变的。
- 隔离性:多个事务同时执行的时候,互相不会产生影响。
- 持久性:事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。
隔离性带来的问题
- 脏读:一个事务读取到了另外一个事务没有提交的数据
- 不可重复读:一个事务读取到了另外一个事务修改的数据
- 幻读:一个事务读取到了另外一个事务新增的数据
通过控制隔离级别解决上述问题。
隔离级别
- 读未提交:允许读取尚未提交的数据,带来上述三个问题
- 读已提交:允许读取并发事务已提交的数据,可以阻止脏读
- 可重复读(默认):对同一字段的多次读取结果都是一致的,可阻止脏读和不可重复读
- 可串行化:所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰