提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
MySQL
数据库分类
关系型数据库 (SQL)
- MySQL,Oracle,SQL server,DB2,SQLlite…
- 通过表和表之间,行和列之间进行数据的存储, 学员信息表,考勤表…
非关系型数据库 (NOSQL) Not Only不仅只有数据库
- Redis,MongDB…
- 非关系型数据库,对象存储,通过对象的自身属性来决定。
MDBS(数据库管理系统)
- 数据库的管理软件,有效的管理,维护,获取数据
- MySQL,数据库管理系统!
使用命令行连接数据库
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vaHg9qMA-1658295200136)(C:\Users\28416\AppData\Roaming\Typora\typora-user-images\image-20220715130159013.png)]
mysql -uroot -pacer -- 连接数据库
所有的语句都使用 ;结尾
show Databases; -- 查看所有的数据库
mysql> use user; -- 切换数据库 use 数据库名
Database changed
show tables; -- 查看数据库中所有的表
describe user; -- 显示数据库中所有表的信息
creat database westor; -- 创建数据库
exit; -- 退出连接
-- 单行注释
/*
多行注释
*/
DDL 定义
DML 操作
DQL 查询
DCL 控制
操作数据库
操作数据库>操作数据库中的表>操作数据库中表的数据
mysql关键字不区分大小写
- 创建数据库
create database if not exists westors; -- 如果不存在westors数据库才创建
- 删除数据库
dorp database if exists westors; -- 如果存在westors数据库就删除
- 使用数据库
-- 如果你的表名或则一个字段是一个特殊字符,就需要带``
use 'westors';
- 查看数据库
show databases; -- 查看所有数据库
数据库的列类型
-
数值
- int 标准的整数 4个字节
- float 浮点数 4个字节
- double 浮点数 8个字节
- decimal 字符串形式的浮点数 金融计算时一般使用!
-
字符串
- char 字符串固定大小 0~255
- varchar 可变字符串 0~65535
- text 文本串 2^16-1 保存大文本
-
事件日期
- date YYYY-MM-DD 日期格式
- time HH:mm:ss 事件格式
- datetime YYYY-MM-DD HH:mm:ss 常用的时间格式
- timestamp 时间戳 1970.1.1 到现在的毫秒数!
- year 年份表示
-
null
-
没有值
-
不要使用NUll进行运算,结果为null
-
创建表
CREATE TABLE IF NOT EXISTS student
(
Id int not null PRIMARY KEY COMMENT '学号',
UserName varchar(10) not null comment '姓名',
Sex VARCHAR(2) NOT NULL COMMENT '性别',
Address varchar(20),
Birth datetime
)
COMMENT:可在字段定义脚本中添加comment属性来添加注释
- 格式
测试了在建表语句中,单引号和双引号都不对,要么表名和字段名都不用引号,要么就用反引号(在波浪线按钮上)
如下:创建user表:
create table if not EXISTS user
(id int UNSIGNED AUTO_INCREMENT,
userName VARCHAR(100) NOT NULL,
passWord VARCHAR(100) NOT NULL,
PRIMARY KEY(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- 也可以加上反引号
create table if not EXISTS `user`
(`id` int UNSIGNED AUTO_INCREMENT,
`userName` VARCHAR(100) NOT NULL,
`passWord` VARCHAR(100) NOT NULL,
PRIMARY KEY(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
- 关于配置ENGINE=InnoDB
innoDB 是 MySQL 上第一个提供外键约束的数据存储引擎,除了提供事务处理外,InnoDB 还支持行锁,提供和 Oracle 一样的一致性的不加锁读取,能增加并发读的用户数量并提高性能,不会增加锁的数量。InnoDB 的设计目标是处理大容量数据时最大化性能,它的 CPU 利用率是其他所有基于磁盘的关系数据库引擎中最有效率的。
- 常用命令
SHOW CREATE TABLE student -- 查看student表的定义语句
DESC student -- 显示表的结构
修改删除表
修改
-- 修改表名
ALTER TABLE student RENAME AS student1;
-- 增加字段
ALTER TABLE student1 ADD age INT(3);
-- 修改表的字段
ALTER TABLE student1 MODIFY age VARCHAR(11); -- 修改约束
ALTER TABLE student1 CHANGE age age1 INT(1); -- 字段重命名
-- 删除表的字段
ALTER TABLE student1 DROP age1;
删除
-- 删除表(如果存在再删除)
DROP TABLE IF EXISTS student1;
所有的创建和删除尽量加上判断,以免报错~
Mysql数据管理
外键
- 方式一:创建表时添加外键
create table `grade`
(
`gradeid` int(10) not null,
`gradename` varchar(50) not null,
PRIMARY KEY(`gradeid`)
)ENGINE=InnoDB DEFAULT CHARSET=gbk
/*
学生表的gradeid字段 要去引用年纪表的 gradeid
定义外键key
给这个外键添加约束(执行引用) references 引用
*/
CREATE TABLE `student1` (
`Id` int(11) NOT NULL COMMENT '学号',
`UserName` varchar(10) NOT NULL COMMENT '姓名',
`gradeid` int(10) not null COMMENT '学生的年纪',
`Sex` varchar(2) NOT NULL COMMENT '性别',
`Address` varchar(20) DEFAULT NULL,
`Birth` datetime DEFAULT NULL,
PRIMARY KEY (`Id`),
KEY `FK_gradeid` (`gradeid`),
CONSTRAINT `FK_gradeid` FOREIGN KEY (`gradeid`) REFERENCES `grade` (`gradeid`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk
删除有外键关系的表时,先删除引用别人的表(从表),再删除被引用的表(主表)
- 方式二:创建表成功后,添加外加按约束
create table `grade`
(
`gradeid` int(10) not null,
`gradename` varchar(50) not null,
PRIMARY KEY(`gradeid`)
)ENGINE=InnoDB DEFAULT CHARSET=gbk
CREATE TABLE `student1` (
`Id` int(11) NOT NULL COMMENT '学号',
`UserName` varchar(10) NOT NULL COMMENT '姓名',
`gradeid` int(10) not null COMMENT '学生的年纪',
`Sex` varchar(2) NOT NULL COMMENT '性别',
`Address` varchar(20) DEFAULT NULL,
`Birth` datetime DEFAULT NULL,
PRIMARY KEY (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk
-- 创建表的时候没有外键关系
ALTER TABLE `student1`
ADD CONSTRAINT `FK_gradeid` FOREIGN KEY(`gradeid`) REFERENCES `grade`(`gradeid`);
以上的操作都是物理外键,数据库级别的外键,不建议使用!(避免数据库过多造成困扰,了解即可~)
最佳实践
- 数据库就是单纯的表,只用来存数据,只有行(数据)和列(字段)
- 我们想使用多张表的数据,想使用外键(程序去实现)
DML语言
数据库意义:数据存储,数据管理
DMl语言:数据库操作语言
- insert
- update
- delete
添加(insert)
create table `grade`
(
`gradeid` int(10) ,
`gradename` varchar(50) not null,
PRIMARY KEY(`gradeid`)
)ENGINE=InnoDB DEFAULT CHARSET=gbk
-- 插入值
INSERT INTO `grade`(`gradename`,`gradeid`) VALUES('大四','2');
-- 插入多个值
INSERT INTO `grade`(`gradeid`,`gradename`) VALUES('1','大一'),('2','大二'),('3','大三')
注意:
-
字段和字段之间使用英文逗号隔开
-
字段是可以省略的,但是后面的值必须要与字段一一对应
INSERT INTO `grade` VALUES('大四','2');
-
可以同时插入多条数据
修改(update)
-- 修改名字
UPDATE `grade` SET `gradename`='狂神' WHERE gradeid=1;
-- 不指定条件的情况下,会改动所有表!!!
UPDATE `grade` SET `gradename`='长江七号';
-- 多个属性,逗号隔开
UPDATE `grade` SET `gradename`='小七',`gradeid`='1010' WHERE gradeid = 1;
UPDATE `grade` SET `gradename`='狂神' WHERE
between…and…
UPDATE `grade` SET `gradename`='狂神' WHERE gradeid BETWEEN 2 AND 3;sdwdsdsdaaasssss
通过多个条件定位数据
UPDATE `grade` SET `gradename`='mysql' WHERE `gradename`='狂神' AND `gradeid`=2;
删除(delete)
CREATE TABLE `test`(
`id` int auto_increment PRIMARY KEY,
`cows` VARCHAR(10) not null
)
INSERT INTO `test`(`cows`) VALUES('a'),('b'),('c');
-- truncate命令,清空一个数据表
TRUNCATE `grade`;
- auto_increment: 字段自增
- deltet 和 truncate的 区别
- 相同点:都能删除数据表,不会删除表结构
- 不同:
- truncate 重新设置自增列技术会归零
- truncate 不会影响事务
DQL查询数据库
(Data Query Language:数据查询语句)
- 所有的查询语句操作都用它 select
- 数据库中最核心的语句,最重要的语句
- 使用频率最高的语句
创建需要用到的表,并插入一些数据
create table `student`(
`studentno` int(4) not null comment '学号',
`loginpwd` varchar(20) default null,
`studentname` varchar(20) default null comment '学生姓名',
`sex` tinyint(1) default null comment '性别,0或1',
`gradeid` int(11) default null comment '年级编号',
`phone` varchar(50) not null comment '联系电话,允许为空',
`address` varchar(255) not null comment '地址,允许为空',
`borndate` datetime default null comment '出生时间',
`email` varchar (50) not null comment '邮箱账号允许为空',
`identitycard` varchar(18) default null comment '身份证号',
primary key (`studentno`),
unique key `identitycard`(`identitycard`),
key `email` (`email`)
)engine=myisam default charset=utf8;
-- 创建年级表
drop table if exists `grade`;
create table `grade`(
`gradeid` int(11) not null auto_increment comment '年级编号',
`gradename` varchar(50) not null comment '年级名称',
primary key (`gradeid`)
) engine=innodb auto_increment = 6 default charset = utf8;
-- 创建科目表
drop table if exists `subject`;
create table `subject`(
`subjectno`int(11) not null auto_increment comment '课程编号',
`subjectname` varchar(50) default null comment '课程名称',
`classhour` int(4) default null comment '学时',
`gradeid` int(4) default null comment '年级编号',
primary key (`subjectno`)
)engine = innodb auto_increment = 19 default charset = utf8;
-- 创建成绩表
drop table if exists `result`;
create table `result`(
`studentno` int(4) not null comment '学号',
`subjectno` int(4) not null comment '课程编号',
`examdate` datetime not null comment '考试日期',
`studentresult` int (4) not null comment '考试成绩',
key `subjectno` (`subjectno`)
)engine = innodb default charset = utf8;
Select
- 查询全部学生
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
- 查询那些学生参加了考试 distinct:去重
/*
SELECT * FROM result -- 查询全部的考试成绩
SELECT `studentno` FROM result -- 查询有那些学生参加了考试
*/
SELECT DISTINCT `studentno` FROM result
- 查询系统的版本
SELECT VERSION()
- 用来计算
SELECT 100*3-1 AS 计算结果 -- 用来计算
-- 学员考试成绩 +1分查看
SELECT `studentno`,`studentresult`+1 AS '提分后' FROM result
Where
作用:检索数据中符合条件的值
- 查询成绩在 90~100之间的
SELECT `studentno`,`studentresult` FROM result WHERE `studentresult`>=90 AND `studentresult`<=100
SELECT `studentno`,`studentresult` FROM result WHERE `studentresult`>=90 && `studentresult`<=100
SELECT `studentno`,`studentresult` FROM result WHERE `studentresult` BETWEEN 91 AND 100 -- 模糊查询(区间)
- 查询除了1001号学生之外的学生成绩
SELECT `studentno`,`studentresult` FROM result WHERE `studentno`!=1001; -- 除了1001号学生和科目1之外的学生科目成绩 SELECT `studentno`,`studentresult` FROM result WHERE `studentno`!=1001 AND `subjectno`<>1;
联表查询
join
操作 | 描述 |
---|---|
inner join | 如果表中至少有一个匹配值,就返回行 |
left join | 会从左表中返回所有的值,即是右表中没有匹配 |
right join | 会从右表中返回所有的值,即是左表中没有匹配 |
-- ========================================================联表查询 join
-- 查询的内容来自不同的表
-- INNER JOIN
-- join on 连接查询
-- where 等值查询
SELECT s.studentno,studentname,subjectno,studentresult
FROM student AS s
INNER JOIN result AS r
WHERE s.studentno = r.studentno
-- right join
SELECT s.studentno,studentname,subjectno,studentresult
FROM student s
RIGHT JOIN result r
ON s.studentno = r.studentno
-- left join
SELECT s.studentno,studentname,subjectno,studentresult
FROM student s
LEFT JOIN result r
ON s.studentno = r.studentno
-- 查询缺考的同学
SELECT s.studentno, studentname,subjectno,studentresult
FROM student s
LEFT JOIN result r
ON s.studentno = r.studentno
WHERE studentresult is NULL
-- 三表查询
SELECT s.studentno,studentname,subjectname,studentresult -- 分别来自student,result,subject
FROM student s
RIGHT JOIN result r
ON r.studentno = s.studentno
INNER JOIN `subject` sub
ON r.subjectno = sub.subjectno
-- 我们要查询那些数据 select ...
-- 从哪几个表中差 From 表 xxx join 连接的表 on 交叉条件
-- 假设存在一种多张表查询,慢慢来,先查询两张表,然后慢慢增加
自连接
自己的表和自己的表连接,核心一张表拆为两张表一样的即可
-- 查询父子关系
SELECT a.categoryname AS '父栏目', b.categoryname AS '子栏目'
FROM category as a,category as b
WHERE a.categoryid=b.pid
分页和排序
分页limit 和 排序 order by
-- ================================分页limit 和排序order by
-- 升序:ASC 降序:DESC
-- 查询的结果根据成绩排序
SELECT s.studentno,studentname,subjectname,studentresult
FROM student s
INNER JOIN result r
ON s.studentno=r.studentno
INNER JOIN `subject` sub
on r.subjectno=sub.subjectno
WHERE subjectname='java'
ORDER BY studentresult ASC
-- 分页
SELECT s.studentno,studentname,subjectname,studentresult
FROM student s
INNER JOIN result r
ON s.studentno=r.studentno
INNER JOIN `subject` sub
on r.subjectno=sub.subjectno
WHERE subjectname='java'
ORDER BY studentresult ASC
LIMIT 0,2
-- 第一页 limtit 0,5 (1-1)*5
-- 第二页 limtit 5,5 (2-1)*5
-- 第三页 limtit 10,5 (3-1)*5
-- 第n页 limtit (n-1)*pagesize
-- 【pagesize:页面大小(显示多少条数据)】
-- 【(n-1)*5:起始值(从那条数据开始显示)】
-- 【n:当前是第几页】
-- 【数据总数、页面大小=总页数】
查询 java成绩大于80的前十名同学
SELECT s.studentno,studentname,subjectname,studentresult
FROM student s
INNER JOIN result r
ON s.studentno=r.studentno
INNER JOIN `subject` sub
on r.subjectno=sub.subjectno
WHERE subjectname='java' AND studentresult>80
ORDER BY studentresult ASC
LIMIT 0,10
子查询
where(这个值是计算出来的)
本质:在where语句中嵌套一个子查询语句
where(select * from)
-- 子查询 =============================================
-- 查询C语言的所有考试结果(学号,科目编号,成绩),降序排列
-- 方式一:使用连接查询
SELECT studentno,r.subjectno,studentresult
FROM result r
INNER JOIN `subject` sub
ON r.subjectno=sub.subjectno
WHERE subjectname='C语言'
ORDER BY studentresult DESC
-- 方式二:使用子查询
SELECT studentno,subjectno,studentresult
FROM result
WHERE subjectno=(
SELECT subjectno FROM `subject` WHERE subjectname='C语言'
)
-- 查询分数不小于88分的学生的学号和姓名
SELECT DISTINCT s.studentno,studentname
FROM student s
INNER JOIN result r
ON s.studentno=r.studentno
WHERE studentresult>=88
-- 在这个基础上增加科目,数学
-- 查询数学 的编号
SELECT DISTINCT s.studentno,studentname
FROM student s
INNER JOIN result r
ON s.studentno=r.studentno
WHERE studentresult>=88 AND subjectno=(
SELECT subjectno FROM `subject`
WHERE subjectname='数学'
)
--
SELECT studentno,studentname FROM student WHERE studentno IN(
SELECT studentno FROM result WHERE studentresult>85 AND subjectno=(
SELECT subjectno FROM `subject` WHERE subjectname='数学'
)
)
MySQL函数
常用函数
-- 数学运算
SELECT ABS(-8) -- 绝对值
SELECT CEILING(9.3) -- 向上取整
SELECT FLOOR(9.3) -- 向下取整
SELECT RAND() -- 返回一个0~1之间的随机数
SELECT SIGN(-10) -- 返回参数的符号 0-0 负数返回-1,正数返回1
-- 字符串函数
SELECT CHAR_LENGTH('即是再小的帆也能远航') -- 字符串长度
SELECT CONCAT('我','来','了') -- 拼接字符串
SELECT INSERT('我爱编程helloworld',1,2,'超级热爱') -- 从某个位置开始替换某个长度
SELECT LOWER('KuangShen') -- 小写字母
SELECT UPPER('KuangShen') -- 大写字母
SELECT INSTR('kuangshen','h') -- 返回第一次出现字符的索引
SELECT REPLACE('坚持就能成功','坚持','努力') -- 替换指定的字符
SELECT SUBSTR('坚持就能成功',2,3) -- 返回指定的字符串(元字符串,截取的位置,截取的长度)
SELECT REVERSE('坚持就能成功') -- 反转
-- 将姓张的改为章
SELECT * FROM student
WHERE studentname LIKE '张%'
--
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()
聚合函数
-- =======================聚合函数=========================================
SELECT COUNT(studentname) FROM student -- COUNT(字段),会忽略所有的null值
SELECT COUNT(*) FROM student -- count(*),不会忽略null值,本质 计算行数
SELECT COUNT(1) FROM result -- 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
数据库MD5加密
-- 创建测试表
CREATE TABLE `testmd5`(
`id` int(4) not null,
`name` VARCHAR(20) not null,
`pwd` VARCHAR(50) not null,
PRIMARY KEY(`id`)
)ENGINE=INNODB CHARSET=utf8
INSERT INTO testmd5 VALUES (1,'张三','123'),(2,'李四','234'),(3,'王五','345')
-- id=1的pwd字段加密加密
UPDATE testmd5 SET pwd=MD5(pwd) WHERE id =1
--
UPDATE testmd5 set pwd=MD5(pwd) -- 全部加密
-- 插入时就加密
INSERT INTO testmd5 VALUES(4,'小明',MD5('123456'))
-- 如何校验:将用户传进来的密码,进行MD5加密,然后比对加密后的值
SELECT * FROM testmd5 WHERE `name`='小明' AND pwd=MD5('123456')
事物
事物:要么都成功,要么都失败
一一一一一
- sql执行 A给B转账 A 1000 —>200 B 200
- sql执行 B收到A的钱 A 800 B 400
一一一一一
将一组sql放在一个批次中去执行~
事物原则:ACID原则 原子性,一致性,隔离性,持久性 (脏读,幻读…)
-
原子性:要么都成功,要么都失败
-
一致性:事物前后的数据完整保证一致
-
持久性:事物一旦提交则不可逆转,被持久化到数据库中!
-
隔离性:针对多个用户同时操作,数据库为每个用户开启的事物,不能被其他事物的操作数据所干扰,事物之间要相互隔离。
隔离所导致的问题
脏读:
指一个事物读取了另一个事物未提交的数据。
不可重复读:
在一个事物内读取表中的某一行数据,多次读取结果不同。(这个不一定是错误,只是读取场合不对)
虚度:
是指在一个事物读取到了别的事物插入的数据,导致前后读取不一致。
-- ===================事物=====================
-- mysql 是默认开启事物自动提交的
SET autocommit = 0 -- 关闭
SET autocommit = 1 -- 开启(默认)
-- 手动处理事物
SET autocommit =0
-- 事物开启
START TRANSACTION -- 标记一个事物的开始,从这个之后的sql都在同一个事物内
INSERT xx
INSERT xx
-- 提价:持久化(成功!)
COMMIT
-- 回滚:回到原来的样子(失败~)
ROLLBACK
-- 事物结束
SET autocommit =1
模拟转账
-- ======================模拟转账=========================
CREATE TABLE `shop`(
`id` INT(3) NOT NULL auto_increment,
`name` VARCHAR(20) NOT NULL,
`money` DECIMAL(9,2) NOT NULL,
PRIMARY KEY(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8
INSERT INTO shop(`name`,`money`) VALUES('A','2000.00'),('B','10000.00')
-- 转账
SET autocommit = 0; -- 环比自动提交
START TRANSACTION; -- 开启事物 -- 1.
UPDATE shop SET money = money-500 WHERE `name`='A'-- A减500 -- 2.
UPDATE shop SET money = money+500 WHERE `name`='B' -- B加500 -- 3.
COMMIT -- 提交 -- 4\5
ROLLBACK; -- 回滚 -- 4\5
SET autocommit = 1; -- 6.
索引
索引(index)是帮助mysql高效获取数据的数据结构,提取句子的主干,就可以得到索引的本质
索引的分类
-
主键索引(PRIMARY KEY)
- 唯一标识,主键不可重复,只能有一个列作为主键
-
唯一索引(UNIQUE KEY)
- 避免重复的列出现,唯一索引可以重复,多个列都可以作为唯一索引
-
常规索引(KEY/INDEX)
- 默认的,index和key关键字来设置
-
全文索引(FullText)
- 在特定的数据库引擎下才有
用户管理
-- 创建用户 CREATE USER 用户名 IDENTIFIED by '密码'
CREATE USER kuangshen IDENTIFIED by '123456'
-- 修改密码(指定用户)
SET PASSWORD FOR kuangshen = PASSWORD('111111');
-- 重命名
RENAME USER kuangshen TO kuangshen2
-- 创建用户 CREATE USER 用户名 IDENTIFIED by '密码'
CREATE USER kuangshen IDENTIFIED by '123456'
-- 修改密码(指定用户)
SET PASSWORD FOR kuangshen = PASSWORD('111111');
-- 重命名
RENAME USER kuangshen TO kuangshen2
-- 用户授权 ALL PRIVILEGES 全部的权限,库.表
-- All PRIVILEGES 除了给别人授权,其他都能干
GRANT ALL PRIVILEGES ON *.* TO kuangshen2
-- 撤销权限
REVOKE ALL PRIVILEGES ON *.* FROM kuangshen2
-- 查看权限
SHOW GRANT FOR kuangshen2 -- 查看指定用户权限
SHOW GRANT FOR root@localhost
-- 删除用户
DROP USER kuangshen2
MySQL备份
备份数据:
- 保证重要数据不丢失
- 数据转移
备份方式:
- 直接拷贝物理文件(data下的)
- 在可视化工具中手动导出
- 使用命令行导出 mysql dump
规范数据库设计
当数据库比较复杂的时候,我们就需要设计了
- 节省内存空间
- 保证数据库的完整性
避免:
- 数据冗余,浪费空间
- 数据插入和删除都会麻烦,异常【屏蔽使用物理外键】
- 程序性能差
为什么需要数据规范?
- 信息重复
- 更新异常
- 插入异常
- 无法正常显示信息
- 删除异常
- 丢失有效的信息
三大范式
第一范式(·NF)
原子性:保证每一列不可再分
第二范式(2NF)
前提:满足第一范式
每张表只描述一件事情
第三范式(3NF)
前提:满足第二范式
确保数据表中的每一列数据都和主键直接相关,二不能间接相关