一、MySQL数据库软件
MySQL的结构
MySQL是一个客户端/服务器的架构,它的服务器程序直接和我们存储的数据打交道,然后可以有好多客户端程序连接到这个服务器程序,发送增删改查的请求,然后服务器就响应这些请求,从而操作它维护的数据。服务器进程对客户端进程发送的请求做了什么处理,才能产生最后的处理结果呢?客户端可以向服务器发送增删改查各类请求,我们这里以比较复杂的查询请求为例来画个图展示一下大致的过程:
存储引擎
MySQL
服务器把数据的存储和提取操作都封装到了一个叫存储引擎
的模块里。我们知道表
是由一行一行的记录组成的,但这只是一个逻辑上的概念,物理上如何表示记录,怎么从表中读取数据,怎么把数据写入具体的物理存储器上,这都是存储引擎
负责的事情。为了实现不同的功能,MySQL
提供了各式各样的存储引擎
,不同存储引擎
管理的表具体的存储结构可能不同,采用的存取算法也可能不同。
登录
- mysql -uroot -p密码
- mysql -hip -uroot -p连接目标的密码
- mysql –host=ip –user=root –password=连接目标的密码
退出
- exit
- quit
MySQL目录结构
MySQL有一个安装目录有一个数据目录,在数据目录中又有这样的几个概念
- 数据库:文件夹
- 表:文件
- 数据:数据
二、SQL
SQL全称为Structured Query Language,即结构化查询语言,其通用的语法有
- SQL 语句可以单行或多行书写,以分号结尾。
- 可使用空格和缩进来增强语句的可读性。
- MySQL 数据库的 SQL 语句不区分大小写,关键字建议使用大写。
- 3 种注释
- 单行注释: – 注释内容 或
- 单行注释:#注释内容(mysql 特有)
- 多行注释: /* 注释 */
根据SQL操作的对象和功能不一样,被分为四大类
-
DDL(Data Definition Language)数据定义语言
用来定义数据库对象:数据库,表,列等。关键字:create,drop,alter 等
-
DML(Data Manipulation Language)数据操作语言
用来对表中数据进行增删改,关键字:insert,delete,update等
-
DQL(Data Query Language)数据查询语言
用来查询数据库中表的记录。关键字:select,where等
-
DCL(Data Control Language)数据控制语言
用来定义数据库的访问权限和安全级别,及创建用户。关键字:GRANT, REVOKE 等
DDL:操作数据库、表
对于DDL语句,可以分为操作数据库和操作表,并且对于数据库和表,又都可以分为CRUD操作,即Create,Retrieve,Update和Delete。
-
操作数据库
1.1 Create:创建
-
创建数据库:
create database 数据库名称;
-
判断数据库是否存在,再创建:
create database if not exists 数据库名称;
-
创建数据库,并制定字符集:
create database 数据库名称 character set 字符集名;
1.2 Retrieve:查询
-
查询所有数据库的名称:
show databases;
-
查询某个数据库的字符集:
show create database 数据库名称;
1.3 Update: 修改
-
修改数据库的字符集
alter database 数据库名称 character set 字符集名称;
1.4 Delete:删除
-
删除数据库
drop database 数据库名称;
-
先判断数据库是否存在,再删除
drop database if exists 数据库名称;
1.5 使用数据库
-
查询当前正在使用的数据库名称
select database();
-
使用数据库
use 数据库名称;
-
-
操作表
2.1 Create:创建
- 创建表
create table 表名( 列名1 数据类型1, 列名2 数据类型2, ... 列名n 数据类型n ); 数据类型: 1. int:整数类型 * age int, 2. double(总位数,小数点后位数):小数类型 * score double(5,2) 3. date:日期,只包含年月日,yyyy-MM-dd 4. datetime:日期,包含年月日时分秒 yyyy-MM-dd HH:mm:ss 5. timestamp:时间错类型 包含年月日时分秒 yyyy-MM-dd HH:mm:ss * 如果将来不给这个字段赋值,或赋值为null,则默认使用当前的系统时间,来自动赋值 6. varchar:字符串 * name varchar(20):姓名最大20个字符复制表
- 复制表
create table 表名 like 被复制表明;
2.2 Retrieve:查询
- 查询某个数据库中所有的表名称
show tables;
- 查询表结构
desc 表明
2.3 Update:修改
- 修改表名
alter table 表名 rename to 新表名;
- 修改表的字符集
alter table 表名 character set 字符集名称;
- 添加一列
alter table 表名 add 列名 数据类型;
- 修改列名称 类型
alter table 表名 change 列名 新列名 新数据类型; alter table 表名 modify 列名 新数据类型
- 删除列
alter table 表名 drop 列名
2.4 Delete:删除
drop table 表名; drop table if exists 表名
DML:增删改表中数据
-
添加数据:
insert into 表名(列名1,列名2,...列名n) values(值1,值2,...值n);
- 注意:
- 列名和值要一一对应。
- 如果表名后,不定义列名,则默认给所有列添加值 insert into 表名 values(值1,值2,…值n);
- 除了数字类型,其他类型需要使用引号(单双都可以)引起来
- 注意:
-
删除数据:
delete from 表名 [where 条件]
- 注意:
- 如果不加条件,则删除表中所有记录。
- 如果要删除所有记录
- delete from 表名; – 不推荐使用。有多少条记录就会执行多少次删除操作
- TRUNCATE TABLE 表名; – 推荐使用,效率更高 先删除表,然后再创建一张一样的表。
- 注意:
-
修改数据:
update 表名 set 列名1 = 值1, 列名2 = 值2,... [where 条件];
- 注意:如果不加任何条件,则会将表中所有记录全部修改。
DQL:查询表中的记录
select * from 表名;
select
字段列表
from
表名列表
where
条件列表
group by
分组字段
having
分组之后的条件
order by
排序
limit
分页限定
-
多个字段的查询
select 字段名1,字段名2... from 表名;
- 注意:如果查询所有字段,则可以使用*来替代字段列表。
-
去除重复:
distinct
-
计算列
- 一般可以使用四则运算计算一些列的值。(一般只会进行数值型的计算)
- ifnull(表达式1,表达式2):null参与的运算,计算结果都为null
- 表达式1:哪个字段需要判断是否为null
- 如果该字段为null后的替换值。
-
起别名:
- as:as也可以省略
-
条件查询:
- where子句后跟条件
- 运算符
- >, <, <=, >=, =, <>
- BETWEEN…AND
- IN(集合 )
- LIKE:模糊查询
- 占位符:
- _:单个任意字符
- %:多个任意字符
- 占位符:
- 不能用!=或者=判断NULL,需要用IS NULL
- and 或 &&
- or 或 ||
- not 或 !
-
排序查询
-
语法:order by 子句
- order by 排序字段1 排序方式1 , 排序字段2 排序方式2…
-
排序方式:
- ASC:升序,默认的。
- DESC:降序。
-
注意:
- 如果有多个排序条件,则当前边的条件值一样时,才会判断第二条件。
-
-
聚合查询:将一列数据作为一个整体,进行纵向的计算。
-
count:计算个数
- 一般选择非空的列:主键
-
max:计算最大值
-
min:计算最小值
-
sum:计算和
-
avg:计算平均值
-
注意:聚合函数的计算,要排除NULL值,可以选择不包含非空的列进行计算,或者使用IFNULL函数
- 分组查询
- 语法:group by 分组字段;
- 注意:
- 分组之后可以查询的字段:分组字段、聚合函数
- where 和 having 的区别?
- where 在分组之前进行限定,如果不满足条件,则不参与分组。having在分组之后进行限定,如果不满足结果,则不会被查询出来
- where 后不可以跟聚合函数,having可以进行聚合函数的判断。
- 分页查询
-
语法:limit 开始的索引,每页查询的条数;
-
公式:开始的索引 = (当前的页码 - 1) * 每页显示的条数 – 每页显示3条记录
SELECT * FROM student LIMIT 0,3; – 第1页
SELECT * FROM student LIMIT 3,3; – 第2页
SELECT * FROM student LIMIT 6,3; – 第3页
-
limit 是一个MySQL"方言"
约束
- 概念:对表中的数据进行限定,保证数据的正确性、有效性和完整性
- 分类:
- 主键约束:primary key
- 非空约束:not null
- 唯一约束:unique
- 外键约束:foreign key
非空约束
值不能为null
- 创建表时添加约束
CREATE TABLE stu(
id INT,
NAME VARCHAR(20) NOT NULL -- name为非空
);
- 创建表完后,添加非空约束
ALTER TABLE stu MODIFY NAME VARCHAR(20) NOT NULL;
- 删除name的非空约束
ALTER TABLE stu MODIFY NAME VARCHAR(20);
唯一约束
值不能重复
- 创建表时,添加唯一约束
CREATE TABLE stu(
id INT,
phone_number VARCHAR(20) UNIQUE -- 添加了唯一约束
);
- 删除唯一约束
ALTER TABLE stu DROP INDEX phone_number;
- 在创建表后,添加唯一约束
ALTER TABLE stu MODIFY phone_number VARCHAR(20) UNIQUE;
主键约束
-
注意:
- 含义:非空且唯一
- 一张表只能有一个字段为主键
- 主键就是表中记录的唯一标识
-
在创建表时,添加主键约束
CREATE TABLE stu(
id int primary key, -- 给id添加主键约束
name varchar(20)
);
- 删除主键
ALTER TABLE stu DROP PRIMARY KEY;
- 创建完表后,添加主键
ALTER TABLE stu MODIFY id INT PRIMARY KEY;
-
自动增长:
- 概念:如果某一列是数值类型,使用
auto_increment
可以来完成值的自动增长 - 在创建表时,添加主键约束,并且完成主键自增长
CREATE TABLE stu( id INT PRIMARY KEY AUTO_INCREMENT, name VARCAHR(20) );
- 删除自动增长
ALTER TABLE stu MODIFY id INT;
- 添加自动增长
ALTER TABLE stu MODIFY id INT AUTO_INCREMENT;
- 概念:如果某一列是数值类型,使用
外键约束
让表与表之间产生关系,从而保证数据的正确性
-
在创建表时,可以添加外键
CREATE TABLE stu( ... constraints 外键名称 foreign key (外键列名) references 主表名称(主表列名称) );
-
删除外键
ALTER TABLE 表名 DROP FOREIGN KEY 外键名称;
- 创建表之后,添加外键
ALTER TABLE 表名 ADD CONSTRAINT 外键名 FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称);
- 级联操作
ALTER TABLE 表名 ADD CONSTRAINT 外键名称
FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称) ON UPDATE CASCADE ON
DELETE CASCADE;
三、多表查询
1. 内连接
隐式内连接
使用where消除无用数据
SELECT * FROM emp,dept WHERE emp.`dept_id` = dept.`id`;
或者使用如下语句,可以给表起别名,从而简化写法
SELECT
t1.name, -- 员工表的姓名
t1.gender,-- 员工表的性别
t2.name -- 部门表的名称
FROM
emp t1, --起别名
dept t2 --起别名
WHERE
t1.`dept_id` = t2.`id`;
显式内连接
select 字段列表 from 表名1 [inner] join 表名2 on 条件
2. 外连接
左外连接:左表以及左表与右表的交集
select 字段列表 from 表1 left [outer] join 表2 on 条件;
右外连接:右表以及右表与左表的交集
select 字段列表 from 表1 right [outer] join 表2 on 条件;
四、子查询
查询中嵌套查询,称嵌套查询为子查询
子查询分为以下三种不同情况:
- 子查询结果是单行单列的,子查询可以作为条件,使用运算符去判断。运算符有:>, >=, <, <=, =
- 子查询的结果是多行单列的:子查询结果可以作为条件,使用运算符
in
来判断 - 子查询的结果是多行多列的:子查询的结果可以作为一个虚拟表,参与查询
五、数据库的设计
1. 多表之间的关系
- 一对一
- 一对一关系实现,可以在任意一方添加唯一外键指向另一方外键,或直接集成在一张表中
- 一对多
- 在多的一方建立外键,指向一的一方主键
- 多对多
- 多对多实现需要借助第三张中间表,中间表至少包含两个字段,这两个字段作为第三张表的外键,分别指向两张表的主键
2. 数据库设计范式
设计数据库时,需要遵循的一些规范。要遵循后边的范式要求,必须先遵循前边的所有范式要求。目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。
- 第一范式(1NF):每一列都是不可分割的原子数据项
- 第二范式(2NF):在1NF的基础上,非码属性必须完全依赖于码(在1NF基础上消除非主属性对主码的部分函数依赖)
- 第三范式(3NF):在2NF的基础上,消除传递依赖
一些概念:
函数依赖:A–>B,如果通过A属性(属性组)的值,可以确定唯一B属性的值。则称B依赖于A 例如:学号–>姓名。 (学号,课程名称) –> 分数
完全函数依赖:A–>B, 如果A是一个属性组,则B属性值得确定需要依赖于A属性组中所有的属性值。 例如:(学号,课程名称) –> 分数
部分函数依赖:A–>B, 如果A是一个属性组,则B属性值得确定只需要依赖于A属性组中某一些值即可。 例如:(学号,课程名称) – > 姓名
传递函数依赖:A–>B, B–>C
例如:学号–>系名,系名–>系主任
码:如果在一张表中,一个属性或者一个属性组,被其他所有属性所完全依赖,则称这个属性(属性组)为该表的码
例如:该表中码为:(学号,课程名称)
- 主属性:码属性组中的所有属性
- 非主属性:除过码属性组的属性
分析上表,学号和课程名称组成的属性组是码,则这两个属性也就是主属性。可见,姓名只需要学号就可以确定,所以对于码而言,是一个部分函数依赖,系所、系主任也是,因此将其剥离,也就是根据第二范式,可以将上表修改为下图。
但此表仍然存在问题,虽然右边的表满足于范式二,但是存在传递函数依赖,如果此时我想设立一个计算机系,然而该系还未招生,就无法把这种关系表现出来,因此继续剥离,变成以下三个表
六、数据库的备份还原
- 命令行:
- 备份: mysqldump -u用户名 -p密码 数据库名称 > 保存的路径
- 还原:
- 登录数据库
- 创建数据库
- 使用数据库
- 执行文件 source 文件路径
- 图形化工具:
七、事务
7.1 概念
如果一个包含多个步骤的业务操作,被事务管理,那么这些操作要么同时成功,要么同时失败。(在提交事务之前, 进行的操作都不针对实际的数据)
- 操作:
- 开启事务:start trasaction;
- 回滚:rollback;
- 提交:commit;
- 事务的提交有两种方式:
- 自动提交:mysql就是自动提交
- 手动提交:需要先开启事务,再提交
- 查询方式:SELECT @@autocommit;
7.2 事务的四大特征
- 原子性:是不可分割的最小单位,要么同时成功,要么同时失败
- 持久性:当事务提交或回滚后,数据库会持久化的保存数据。
- 隔离性:多个事务之间。相互独立。
- 一致性:事务操作前后,数据总量不变。
7.3 事务的隔离级别
-
概念:多个事务之间本应该隔离的,相互独立的,如果多个事务操作同一批数据,会引发一些问题,设置不同的隔离级别可以解决这些问题
-
存在问题:
- 脏读:一个失误,读取到另一个事务中没有提交的数据。
- 不可重复读:在同一个事务中,两次读取到的数据不一样。
- 幻读:一个事务操作数据表中所有记录,另一个事务添加了一条数据,则第一个事务查询不到自己的修改(mysql不能存在)
-
隔离级别
- read uncommitted:读未提交
- 产生问题:脏读、不可重复读、幻读
- read committed:读已提交
- 残生问题:不可重复读、幻读
- repeatable read:可重复度
- 产生问题:幻读
- serializable:串行化
- 可解决所有问题
- read uncommitted:读未提交