文章目录
一、数据库分类
关系型数据库:
MySQL
,Oracle
,SqlServer
,DB2
,SQLlite
等- 通过表和表之间,行和列之间的关系进行存储
非关系型数据库:
Redis
,MongoDB
- 对象存储,通过对象和自身的属性决定
二、MySQL优势
- 简单易学,具有很强的操作性
- 绝大多数重要的数据库管理系统均支持
SQL
- 高度非过程化;用
SQL
操作数据库时大部分的工作由DBMS
自动完成 - 体积小,速度快,总体成本低
三、连接数据库
mysql -u`用户名` -p`密码`
mysql -uroot -p123456 --连接数据库
show databases; --查看所有数据库
use blog; --切换数据库 use 数据库名
show tables; --查看数据库中所有的表
desc t_user; --查看表中的结构信息
create database westors; --创建一个数据库
exit --退出连接
----------------------------------------------
-- 单行注释(SQL本身的注释)
/*
多行注释
*/
三、SQL的分类
- DDL(Data Definition Language) 数据定义语言:用来操作数据库、表、列等; 常用语句:
CREATE
、ALTER
、DROP
- DML(Data Manipulation Language) 数据操作语言:用来操作数据库中表里的数据;常用语句:
INSERT
、UPDATE
、DELETE
- DCL(Data Control Language) 数据控制语言:用来操作访问权限和安全级别; 常用语句:
GRANT
、DENY
- DQL(Data Query Language) 数据查询语言:,用来查询数据 常用语句:
SELECT
四、操作数据库
4. 1数据库操作
- 创建数据库
CREATE DATABASE IF NOT EXISTS westors;
- 删除数据库
DROP DATABASE IF EXISTS westors;
- 使用数据库
-- tab键的上面如果你的表名或者字段名是一个特殊字符,需要带``
USE `school`;
- 查看所有数据库
SHOW DATABASES;
- 查看创建数据库的语句
SHOW CREATE DATABASE school;
4.2 数据库的列类型
数值
类型 | 字节数 | 描述 |
---|---|---|
tinyint | 1 | 非常小的数据 |
smallint | 2 | 较小的数据 |
mediumint | 3 | 中等大小的数据 |
int | 4 | 标准的整数 |
bigint | 8 | 较大的数据 |
float | 4 | 浮点数(单精度) |
double | 8 | 浮点数(双精度) |
decimal | 根据具体位数决定 | 字符串形式浮点数(金融常用) |
字符串
类型 | 字节数 | 描述 |
---|---|---|
char | 0~255 | 字符串固定大小 |
varchar | 0~65535 | 可变字符串 |
tinytext | 2^8-1 | 微型文本 |
text | 2^16-1 | 文本串 |
时间和日期
类型 | 格式 | 描述 |
---|---|---|
date | YYYY-MM-DD | 日期格式 |
time | HH: mm: ss | 时间格式 |
datatime | YYYY-MM-DD HH: mm: ss | 日期时间格式 |
timestamp | 时间戳 | 1970.1.1 到现在的毫秒数 |
yaer | YYYY | 年份表示 |
null
- 没有值,未知
- 不要使用null进行运算,否则结果依旧为null
4.3 数据库的字段属性
- 填充0:不足的位数,使用0来填充
int(3) 5---005
- 无符号:声明了该列
不能声明为负数
- 自增: 自动在上一条记录的基础上
+1
- 可以自定义自增的起始值和步长
- 非空:
NULL``````NOT NULL
- 假设为
NOT NULL
,不对该列赋值就会报错 NULL
,如果不填写值,默认就是NULL
- 假设为
- 默认: 设置默认值
五、表
5.1 创建表
--创建表
-- 注意点:使用英文括号, 表的名称和字段用``括起来
CREATE TABLE IF NOT EXISTS `teacher`(
-- auto_increment:自增长
`id` INT(4) auto_increment NOT NULL COMMENT '学号',
`name` VARCHAR(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',
`pwd` VARCHAR(20) NOT NULL DEFAULT '123456' COMMENT '密码',
`sex` VARCHAR(2) NOT NULL DEFAULT '男' COMMENT '性别',
`birthday` DATETIME DEFAULT NULL COMMENT '出生日期',
`address` VARCHAR(100) DEFAULT NULL COMMENT '家庭住址',
`email` VARCHAR(50) DEFAULT NULL COMMENT '邮箱',
-- 设置主键
PRIMARY KEY (`id`)
-- 设置数据库引擎和字符集
) ENGINE = INNODB DEFAULT CHARSET=utf8;
格式
CREATE TABLE [IF NOT EXISTS] `表名`(
'字段名1' 列类名 [属性] [索引] [注释],
...
'字段名3' 列类名 [属性] [索引] [注释]
)[表类型][字符集设置][表注释];
常用命令
SHOW CREATE DATABASE teacher; --查看teacher表的定义语句
DESC teacher; --显示表的结构
关于数据库引擎
功能 | MYISAM | INNODB |
---|---|---|
事务支持 | 不支持 | 支持 |
数据行锁定 | 不支持 | 支持 |
外键约束 | 不支持 | 支持 |
全文索引 | 支持 | 不支持 |
占用表空间大小 | 较小 | 较大,约为MYISAM两倍 |
特点:
MYISAM
节约空间,速度较快INNODB
安全性高,事务处理,多表多用户操作
5.2 操作表
修改表名称
--格式:ALTER TABLE 旧表名 RENAME AS 新表名;
ALTER TABLE teacher RENAME AS teacher1;
增加表字段
-- 格式: ALTER TABLE 表名 ADD 字段名 列属性;
ALTER TABLE teacher1 ADD age INT(11);
修改表字段约束(重命名、修改)
-- 格式:ALTER TABLE 表名 MODIFY 字段名 列属性[];
ALTER TABLE teacher1 MODIFY age VARCHAR(11); --修改约束
-- 格式:ALTER TABLE 表名 CHANGE 旧字段名 新字段名 列属性[];
ALTER TABLE teacher1 CHANGE age age1 INT(1); --重命名
删除表字段
-- 格式:ALTER TABLE 表名 DROP 字段名;
ALTER TABLE teacher1 DROP age1;
删除表操作
--删除表
-- 格式: DROP TABLE [IF EXISTS] 表名;
DROP TABLE IF EXISTS teacher1;
注意:所有的创建和删除尽量加上判断,以免报错~
六、MySQL数据管理
6.1 外键(了解)
- 在创建表的时候增加约束(麻烦复杂)
-- 创建年级表
CREATE TABLE `grade` (
`gradeid` INT(10) auto_increment NOT NULL COMMENT '年级Id',
`gradename` VARCHAR(50) NOT NULL COMMENT '年级名称',
PRIMARY KEY(`gradeid`)
) ENGINE = INNODB DEFAULT CHARSET=utf8;
-- 创建teacher表
CREATE TABLE IF NOT EXISTS `teacher`(
`id` INT(4) auto_increment NOT NULL COMMENT '学号',
`name` VARCHAR(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',
`pwd` VARCHAR(20) NOT NULL DEFAULT '123456' COMMENT '密码',
`sex` VARCHAR(2) NOT NULL DEFAULT '男' COMMENT '性别',
`birthday` 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`),
-- 执行为外键并引用到grade表
CONSTRAINT `FK_gradeid` FOREIGN KEY (`gradeid`) REFERENCES `grade`(`gradeid`)
-- 设置字符集
) ENGINE = INNODB DEFAULT CHARSET=utf8;
删除有外键关系的表的时候,必须先删除引用别人的表(从表),再删除被引用的表(主表)
- 创建表中没有外键关系,设计表中添加外键
-- 创建teacher表
CREATE TABLE IF NOT EXISTS `teacher`(
`id` INT(4) auto_increment NOT NULL COMMENT '学号',
`name` VARCHAR(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',
`pwd` VARCHAR(20) NOT NULL DEFAULT '123456' COMMENT '密码',
`sex` VARCHAR(2) NOT NULL DEFAULT '男' COMMENT '性别',
`birthday` 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 `表名` ADD CONSTRAINT `约束名` FOREIGN KEY(`作为外键的列`) REFERENCES `引用的表`(`作为外键的列`);
ALTER TABLE `teacher`
ADD CONSTRAINT `FK_gradeid` FOREIGN KEY(`gradeid`) REFERENCES `grade`(`gradeid`);
以上的操作都是物理外键,数据库级别的外键,我们不建议使用(避免数据表太多造成困扰)
最佳实践:
数据库就是单纯的表,只用来存数据,只有行(数据)和列(字段)
想使用多张表的数据,想使用外键用逻辑去实现
6.2 DML语言(增删改,重点)
DML语言:数据库操作语言
insert
update
delete
6.2.1 添加(insert)
-- INSERT INTO 表名([字段名1, 字段名2, 字段名3...]) VALUES('值1'), ('值2'), ('值3')...
--一个字段插入一个值
INSERT INTO `grade`(`gradename`) VALUES('大四');
-- 一个字段插入多个值
INSERT INTO `grade`(`gradename`) VALUES('大一'), ('大二');
-- 多个字段插入一个值
INSERT INTO `teacher`(`name`, `pwd`, `sex`, `gradeid`) VALUES('张三', 'aaaaaa','女', 1);
-- 多个字段插入多个值
INSERT INTO `teacher`(`name`, `pwd`, `sex`, `gradeid`) VALUES('李四', 'ccccccc','男', 3), ('李四', 'bbbbbb','女', 2);
--
注意:
- 插入时一定要保证数据和字段一一对应
- 字段是可以省略的,但是后边得值需要一一对应,不能少
- 可以同时插入多条数据,VALUES后面的值,需要使用’,'隔开
6.2.2 修改(update)
修改谁 (条件) set 原来的值, 新值
-- UPDATE `表名` SET `字段名`=字段值(可以为变量) [WHERE 条件];
-- 指定条件修改语句,修改id为1的name为XXX
UPDATE `teacher` SET `name`='XXX' WHERE id = 1;
-- 不指定条件情况下,会改动所有的表
UPDATE `teacher` SET `name`='XXX';
-- 修改多个字段的值
UPDATE `teacher` SET `name`='任洪彬', `email`='1239279122@168.com' WHERE id = 1;
-- 修改id为2到3之间的数据
UPDATE `teacher` SET `name`='小明', `email`='1239279122@168.com' WHERE id BETWEEN 2 AND 3;
条件:WHERE字句,运算符(会返回布尔值
),id等于大于某个值,大于某个值,在某个区间内修改…
操作符 | 含义 |
---|---|
= | 等于 |
<>或!= | 不等于 |
> | 大于 |
< | 小于 |
<= | 小于等于 |
>= | 大于或等于 |
BETWEEN | 在某个范围内(闭合区间) |
AND | 且 |
OR | 或 |
-- 通过多个条件修改数据
UPDATE `teacher` SET `name`='小红', `email`='1239279122@wang.com' WHERE id BETWEEN 2 AND 3 AND `sex`='男';
6.2.3 删除
delete
命令
-- DELETE FROM `表名` WHERE 字段名=字段值
--删除数据(避免,会删除全部数据)
DELETE FROM `teacher`;
-- 删除指定数据
-- DELETE FROM `teacher` WHERE id=1;
truncate
命令
作用:完全清空数据库表(表结构索引不变)
-- 清空表
TRUNCATE `teacher`;
truncate
和delete
的区别- 相同点:都能删除数据,都不会删除表结构
- 不同:
truncate
重新设置自增序列,计数器归0truncate
不会影响事务
七、DQL查询数据(最重点)
7.1 DQL
综合语法(顺序很重要)
SELECT [ALL | DISTINCT]
{* | table.* | [table.fieild1[as alias1][table.fieild2[as alias2]][,...]}
FROM table_name [AS table_alias]
[LEFT | RIGHT | INNER JOIN table_name2] --联合查询
[WHERE ...] --指定结果需要满足的条件
[GROUP BY ...] --指定按照哪几个字段来分组
[HAVING] --过滤分组的记录必须满足的次要条件
[ORDER BY ...] --指定查询记录按一个或者多个条件排序
[LIMIT {[offset,] row_count | row_countOFFSET offset}] --分页,指定查询的记录起始值, 每页的数据
查询全部博客
-- 语法: SELECT * FROM 表名;
SELECT * FROM t_blog;
查询指定字段
-- 语法:SELECT `字段名1`, `字段名2` FROM 表名;
SELECT `blogTime`, `blogTitle` FROM t_blog;
别名,给结果起名字,也可以给表起别名
-- 语法:SELECT `字段名1` AS 别名1, `字段名2` AS 别名2 FROM 表名;
SELECT `blogTime` AS 博客时间, `blogTitle` AS 博客标题 FROM t_blog;
函数
Concat(a,b)
查询出来后拼接字符串
-- 语法: SELECT CONCAT('字符串',字段名) AS 别名 FROM 表名;
SELECT CONCAT('博客时间: ',blogTime) AS 新时间 FROM t_blog;
AS:
有的时候列名字不是那么见名知意,介意用AS
来取别名 字段名 AS 别名 表名 AS 别名
发现重复数据去重
-- 语法:SELECT DISTINCT `字段名` FROM 表名;
SELECT DISTINCT `isDelete` FROM t_blog;
7.2 where条件字句
逻辑运算符
运算符 | 语法 | 描述 |
---|---|---|
and && | a and b a&&b | 逻辑与,两个都为真结果为真 |
or || | a or b a||b | 逻辑或,其中一个为真,结果为真 |
Not ! | not a !a | 逻辑非,取反 |
SELECT `blogId`, `blogTitle` FROM t_blog WHERE blogId > 1 && blogId < 4;
SELECT `blogId`, `blogTitle` FROM t_blog WHERE blogId < 2 || blogId > 3;
SELECT `blogId`, `blogTitle` FROM t_blog WHERE blogId != 1;
7.3 模糊查询
比较运算符:
运算符 | 语法 | 描述 |
---|---|---|
IS NULL | a IS NULL | 如果操作符为NULL,结果为真 |
IS NOT NULL | a IS NOT NULL | 如果操作符为NULL, 结果为假 |
BETWEEN | a BETWEEN b AND C | 若a在b和c之间,则结果为真 |
LIKE | a LIKE b | SQL匹配, 如果a匹配b,则结果为真 |
IN | a IN (a1, a2,a3…) | a在a1或者a2或者a3…其中某一个时结果为真 |
like结合% 查询最后字符是世界的博客
SELECT `blogId`, `blogTitle` FROM t_blog WHERE `blogTitle` LIKE '%世界';
like结合%
查询中间带世字符的博客
SELECT `blogId`, `blogTitle` FROM t_blog WHERE `blogTitle` LIKE '%世%';
LICK结合_
查询第三个字符是世的博客
SELECT `blogId`, `blogTitle` FROM t_blog WHERE `blogTitle` LIKE '_的世界';
IN
查询包含’阿波罗’, '我的世界’的博客
SELECT `blogId`, `blogTitle` FROM t_blog WHERE `blogTitle` IN ('阿波罗', '我的世界');
查询 博客标题为空的博客
SELECT `blogId`, `blogTitle` FROM t_blog WHERE `blogTitle` IS NULL;
查询 博客标题不为空的博客
SELECT `blogId`, `blogTitle` FROM t_blog WHERE `blogTitle` IS NOT NULL;
7.4 连表查询
操作 | 描述 |
---|---|
INNER JOIN | 如果表中至少有一个匹配,就返回行 |
RIGHT JOIN | 会从右表中返回所有的值, 即使左表中没有匹配 |
LEFT JOIN | 即使右表中没有匹配,也会从左表中返回所有的值 |
-- INNER JOIN 交集查询
SELECT `blogId`, `blogTitle`, t.classId, `className`
FROM t_blog AS t
INNER JOIN t_class c
ON t.classId = c.classId;
-- RIGHT JOIN 以右边的t_class表为基准
SELECT `blogId`, `blogTitle`, t.classId, `className`
FROM t_blog AS t
RIGHT JOIN t_class c
ON t.classId = c.classId;
-- LEFT JOIN 以左边的t_blog表为基准
-- 查询分类为空的博客
SELECT `blogId`, `blogTitle`, t.classId, `className`
FROM t_blog AS t
LEFT JOIN t_class c
ON t.classId = c.classId
WHERE c.classId IS NULL;
自连接
自己的表进而自己的表连接,核心:一张表拆为两张表即可
父类:
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`;
7.5 排序和分页
降序
DESC
升序ASC
-- 格式:SELECT `字段名` FEOM 表名 ORDER BY `需要排序的字段名` 排序方式
-- 降序
SELECT `categoryid`, `pid`, `categoryName` FROM `category`
ORDER BY `categoryid` DESC;
--升序
SELECT `categoryid`, `pid`, `categoryName` FROM `category`
ORDER BY `categoryid` ASC;
排序 LIMIT
-- 格式:SELECT `字段名` FEOM 表名 LIMIT 起始值(n-1) * pageSize, 每页的数据(pageNum);
SELECT `categoryid`, `pid`, `categoryName` FROM `category`
ORDER BY `categoryid` DESC
LIMIT 5, 5;
7.6 子查询
where(这个值是计算得来的)
本质:在where语句中嵌套一个子查询语句
SELECT `StudentNo`, `SubjectNo`, `StudentResult`
FROM `result`
WHERE `SubjectNo` = (
SELECT `SubjectNo` FROM `subject`
WHERE `SubjectName` = ''数据库结构-1
)
ORDER BY `StudentResult` DESC;
7.7 分组过滤
-- 查询不同老师的平均分,最高分,最低分,平均分大于70分
-- 核心,根据不同的年级分组
SELECT `gradename`, AVG(`result`) AS 平均分, MAX(`result`), MIN(`result`)
FROM teacher r
INNER JOIN `grade` g
ON r.gradeid = g.gradeid
GROUP BY r.gradeid -- 通过什么一段来分组
HAVING 平均分>70; --分组需要满足的次要条件
八、MySQL函数
8.1常用函数
数学运算
SElECT ABS(-8); -- 8(绝对值)
SELECT CEILING(9.4) --10向上取整)
SELECT FLOOR(9.4) --9(向下取整)
SELECT RAND() --0~1之间随机数
SELECT SIGN(10) --1(判断一个数的符号 负数返回-1 正数返回1 0返回0)
字符串运算
SELECT CHAR_LENGTH('即使再小的帆也能远航') --10(字符串长度)
SELECT CONCAT('我', '爱', '编程') -- 我爱编程(拼接字符串)
SELECT INSERT('我爱编程helloword', 1, 2, '超级热爱') -- 超级热爱编程helloword(查询,替换,从某个位置开始替换某个长度)
SELECT LOWER() --helloword(转小写)
SELECT UPPER('HeeloWord') -- HEELOWORD(转大写)
SELECT INSTR('hello word', 'l') --3(返回第一次出现子串的索引)
SELECT REPLACE('坚持就能成功', '就能', '可以') -- 坚持可以成功(替换出现的指定字符串)
SELECT SUBSTR('坚持就能成功', 3, 4) -- 就能成功(从第三个开始截取4个字符)
SELECT REVERSE('坚持就能成功') -- 功成能就持坚(反转)
8.2 聚合函数(重点)
函数名称 | 描述 |
---|---|
COUNT() | 计数 |
SUM() | 求和 |
AVG() | 平均值 |
MAX() | 最大值 |
MIN() | 最小值 |
… | … |
--======查询一个表中有多少条记录用COUNT=========
SELECT COUNT(`studentname`) FROM student; --计数含有studentname的数量, 会忽略所有的null值
SELECT COUNT(*) FROM student; --不会忽略null值,如果只有一个字段效率高于COUNT(1)
SELECT COUNT(1) FROM student; --不会忽略null值,如果有多个字段效率高于COUNT(*)
SELECT SUM(`StudentResult`) AS 总和 FROM result; -- 求总分
SELECT AVG(`StudentResult`) AS 平均分 FROM result; -- 求平均分
SELECT MAX(`StudentResult`) AS 最高分 FROM result; --求最高分
SELECT MIN(`StudentResult`) AS 最低分 FROM result; --求最低分
8.3数据库级别MD5
加密(了解)
特点:
- 主要增强算法复杂度和不可逆性
MD5
不可逆,具体的值的MD5
是一样的
-- 插入的时候加密
INSERT INTO `表名` VALUES(4, 'xiaoming', MD5('123456')
-- 校验
SELECT * FROM `表名` WHERE `userName`='xiaoming' AND pwd=MD5('123456')
九、事务(重要)
9.1 什么是事务?
要么都成功,要么都失败
举例:
SQL
执行转账 A给B转账 A1000 ------> 200 B200SQL
执行 B收到A的钱 A800 ------>B400
在转账的时候只有全部操作成功,才代表转账成功,只要有一次操作不成功,就转账失败
事务原则:
ACID
- 原子性(Atomicity):针对同一个事务,要么都完成,要么都失败(要么转账成功,要么转账失败)
- 一致性(Consistency):数据前端的完整性要保持一致(无论怎么转,钱的总数不变)
- 持久性(Durability):事务一旦提交不可逆,被持久化到数据库中(保证用户的钱不会由于其它因素丢失)
- 隔离性(Isolation): 针对多个用户并发访问数据库时,主要排除其它事务对本次事务的影响(保证多个用户同时转账不受影响)
事务隔离中存在的问题
- 脏读:值一个事务读取了另一个事务未提交的数据
- 不接重复读: 在一个事务内读取表中的某一行数据,多次读取结果不同.(这个不一定是错误,知识某些场合不对)
- 幻读(虚读):指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致(一般为行影响)
9.2 MySQL事务实现
MySQL是默认开启事务地洞提交的
事务自动提交开启/关闭
SET autocommit = 0; -- 关闭
SET autocommit = 1; -- 开启
基本流程:
手动处理事务
SET autocommit = 0; -- 关闭
事务启动
START TRANSACTION --标记一个事务的开始,从这个之后的SQL都在同一个事务内
提交: 持久化(成功!)
COMMIT
回滚: 回到原来的状态(失败!)
ROLLBACK
事务结束
SET autocommit = 1 --开启自动提交
其它(了解)
SAVEPOINT 保存点名 --设置一个事务的保存点
ROLLBACK TO SAVEPOINT -- 回滚到保存点
RELEASE SAVEPOINT --撤销保存点
转账实现
-- 模拟转账
SET autocommit = 0; -- 关闭自动提交
START TRANSACTION; -- 开启一个事务(一组事务)
UPDATE `account` SET money=money-500 WHERE `name` = 'A'; -- A减500
UPDATE `account` SET money=money+500 WHERE `name` = 'B'; -- B加500
COMMIT; -- 提交事务,持久化
ROLLBACK; -- 回滚
SET autocommit = 1; -- 恢复默认值
十、索引
MySQL
官方对索引的定义:索引(index)是帮助MySQL高效获取数据的数据结构,及索引就是数据结构,用来挺高查询效率
10.1 索引的分类
主键索引 (PRIMARY KEY)
- 唯一标识,主键不可以重复,只有一个列作为主键
唯一索引 (UNIQUE KEY)
- 避免重复的列出现,唯一索引可以重复, 多个列都可以标识为唯一索引
常规索引 (KEY/INDEX)
- 默认的,INNDEX或KEY关键字设置
全文索引 (FULLTEXT)
- 快速定位数据(有些引擎不支持)
显示所有的索引信息
SHOW INDEX FROM `表名`;
增加一个全文索引
ALTER TABLE 数据库名.表名 ADD FULLTEXT INDEX `索引名`(`字段名`)
分析SQL执行状况
EXPLAIN SELECT * FROM `表名`; --非全文索引
EXPLAIN SELECT * FROM `表名` WHERE MATCH(`索引名`) AGAINST('xxx'); --索引匹配xxx
- 索引在小数据量的时候用处不大,但是在大数据的时候,区别十分明显~
10.2 索引原则
- 索引不是越多越好
- 不要对进程变动数据加索引
- 小数据量的表不需要加索引
- 索引一般加在常用来查询的字段上
索引的数据结构
Hash
类型的索引Btree
:INNODB
的默认数据结构
细节可以看这篇文章
十一、权限管理和备份(了解)
11.1 权限管理
SQL
命令操作权限
对mysql.user表进行增删改查
创建一个用户
CREATE USER `用户名` IDENTIFIED BY '密码';
修改密码(修改当前用户密码)
SET PASSWORD = PASSWORD('新密码');
修改密码(修改指定密码)
SET PASSWORD FOR 用户名 = PASSWORD('新密码')
重命名用户
RENAME USER 旧用户名 TO 新用户名
用户设置授权
GRANT ALL PRIVILEGES ON *.*; -- 授予所有表的全部权限,除了给别人授权,其它都能做
查询指定用户权限
SHOW GRANTS FOR 用户名
SHOW GRANTS FOR root@localhost --查询root的权限
撤销权限
REVOKE ALL PRIVILEGES ON *.* FROM 用户名 -- 撤销用户名的所有权限
删除用户
DROP USER 用户名
11.2 MySQL备份
为什么要备份:
- 保证重要的数据不丢失
- 数据转移
MySQL
数据库备份的方式 - 直接拷贝物理文件
- 在可视化工具手动导出(转储为
SQL
文件) - 使用命令行导出
mysqldump
# mysqldump -h 主机 -u用户名 -p密码 数据库 表名 >物理磁盘位置/文件名
mysqldump -hlocalhost -uroot -p123456 school student >D:/a.sql
十二、规范数据库设计
12.1 为什么需要设计
当数据库比较复杂时,我们就要进行设计
糟糕的数据库设计:
- 数据冗余,浪费空间
- 数据库插入和删除都很麻烦,异常[屏蔽使用物理外键]
- 程序性能差
良好的数据库设计:
- 节省内存空间
- 保证数据的完整性
- 方便开发系统
软件开发中关于数据库的设计:
- 分析需求:分析业务和需要处理的数据库需求
- 概要设计:设计E-R图
设计数据库的步骤:(个人博客举例)
- 收集信息,分析需求
1.1 用户表(用户登录注销,用户个人信息,写博客,创建分类)
1.2 分类表(文章分类,谁创建的)
1.3 文章表(文章的信息)
1.4 友链表(友链信息)
1.5 自定义表(系统信息, 某个关键文字, 或者一些字段) key:value - 标识实体类(把需求落地到字段上)
- 标识实体之间的关系
3.1 写博客:user—>blog
3.2创建博客: user —> category
3.3 关注: user —> user
3.4 友链: links
3.5 评论: user —> user --> blog
12.2 三大范式
为什么需要数据库规范化?
- 信息重复
- 更新异常
- 插入异常
- 无法正常显示信息
- 删除异常
- 丢失有效的信息
三大范式
第一范式(1NF):
- 要求数据库表中的每一列都是不可再分的原子数据项
第二范式(2NF):
- 前提:满足第一范式
- 每张表只描述一件事情
第三范式(3NF):
- 前提:满足第一范式和第二范式
- 需要确保数据表中的每一列数据都与主键直接相关,而不能间接相关
规范性和性能的冲突:
阿里规范:关联查询的表不能超过三张表
具体参考:
- 考虑商业化的需求和目标(成本和用户体验),数据库的性能更加重要
- 在规范性能问题时需要适当的考虑规范性!
- 尽量从多表查询变成单表查询
- 故意增加一些计算列(从大数据量降低为小数据量的查询)