MySQL学习
数据库分类:
关系型数据库:MySQL oracle sqlserver
内存数据库: memcache redis
数据库技术概述
数据库系统的三级模式-两层映射
-
模式(逻辑模式):描述的是数据的全局逻辑结构;一个模式可以有任意多个外模式;数据库只有一个模式
-
外模式(子模式/用户模式):描述的是数据的局部逻辑结构;面向具体的应用程序
-
内模式(存储模式):描述数据物理结构和存储结构;例如记录的存储方式是顺序存储、按照B树结构存储还是按hash方式存储;
两层映射是为了能够在内部实现三个抽象层次的联系和转换。保证了数据较高的逻辑独立性和物理独立性 -
外模式/模式映像:每一个外模式都有一个外模式/模式映像
当模式改变(例如增加新的数据类型、新的数据项)时,由数据库管理员对各个外模式/模式的映像做相应改变。 -
模式/内模式映像:是唯一的
定义了数据全局逻辑结果与存储结构之间的对应关系。例如:说明逻辑记录和字段在内部是如何表示。
外模式:视图级;模式是表级;内模式是文件级
数据库设计过程
产生文档:
分四个阶段:
- 需求分析:产生一组数据流图(DFD)和数据字典
- 概念结构设计
- 逻辑结构设计
- 物理设计
E-R模型
实体:矩形;分为弱实体和强实体
属性:椭圆
联系:菱形
分类:1:1联系
规范化理论
- 数据冗余
- 修改异常
- 插入异常
- 删除异常
数据库完整性约束
- 实体完整性约束
- 参照完整性约束
- 用户自定义完整性约束
- 触发器
MySQL概述
- MySQL是一个关系型数据库管理系统,属于Oracle旗下产品。
- MySQL开发者为瑞典MySQL AB公司,2008年1月被Sun公司收购,2009年Sun又被Oracle收购
- 版本
5.5: InnoDB作为默认的数据库存储引擎
5.6(推荐)
5.7
8.0(开发版) - 特点
- 使用C和C++编写,多种编译器进行测试,保证源代码的可移植性
- 支持FreeBSD、Linux、Mac OS、OpenBSD等多种操作系统
- 为多种语言提供API
- 支持多线程,充分利用CPU资源
- 优化的SQL查询算法,有效地提高了查询速度
- 提供用于管理、检查、优化数据库操作的管理工具
- 可以处理拥有上千万条记录的大型数据库
相关名词
数据库database
数据表table
字段column(字段类型)
列column
行row
数据类型和运算符
MySQL支持的数据类型主要分为3类:数字类型、字符串类型、日期和时间类型
数字类型
数据类型 | 取值范围 | 单位 |
---|---|---|
TINYINT | -128-127(sign) 0-255(unsign) | 1字节 |
SMALLINT | -32768-32767(sign) 0-65535(unsigned) | 2字节 |
MEDIUMINT | 中型整数 | 3字节 |
INT | 标准整数 | 4字节 |
BIGINT | 大整数 | 8字节 |
FLOAT | 单精度浮点数 | 8或4字节 |
DOUBLE | 双精度浮点型 | 8字节 |
DECIMAL | 取值范围可变 | 自定义长度 |
定点数:decimal(m,d): m总长,d小数点数
例如:decimal(9,2) 最大是9999999.99
字符串类型
分三类:普通的文本字符串类型CHAR和VARCHAR;TEXT和BLOB类型;特殊类型SET和ENUM
类型 | 取值范围 | 说明 |
---|---|---|
CHAR | 0-255个字符 | 固定长度为M的字符串 |
VARCHAR | 0-255个字符 | 可变长度,其他与CHAR类似 |
TINYTEXT | 2^8-1(255字节数) | 小TEXT字段 |
TEXT | 2^16-1(65535字节数) | 常规TEXT字段 |
MEDIUMTEXT | 2^24-1(16777215个字节数) | 中型TEXT字段 |
LONGTEXT | 2^32-1 | 长TEXT字段 |
SET | 最大值64 | 该类型的列可以容纳一组值或为NULL |
ENUM | 最大值65535 | 该类型的列只可以容纳所列值之一或为NULL |
遵循原则:
- 从速度方面考虑,要选择固定的列,使用CHAR类型
- 要节省空间,使用动态的列,可以使用VARCHAR类型
- 允许在一个列中有多于一个的条目,可以使用SET类型
- 如果要搜索的内容不区分大小写,可以使用TEXT类型
- 如果要搜索的内容区分大小写,可以使用BLOB类型
日期和时间类型
日期和时间类型包括DATETIME、DATE、TIMESTAMP、TIME和YEAR
类型 | 格式 | 长度 |
---|---|---|
DATE | YYYY-MM-DD | 3字节 |
TIME | HH:MM:SS | 3字节 |
YEAR | YYYY | 1字节 |
DATETIME | YYYY-DD-MM HH:MM:SS | 8字节 |
TIMESTAMP | YYYYMMDD HHMMSS | 8字节 |
MariaDB [shop]> select NOW();
| 2019-02-22 18:42:24 |
SQL语句
列名的修饰
修饰 |
---|
unsigned(无符号) |
auto_increment(自增) |
default(默认值) |
comment(字段解释说明) |
not null null(非空) |
unique(索引) |
index(索引) |
key(索引) |
primary key(主键) |
auto_increment 必须定制为primary key |
SQL语句的分类
DDL 数据定义语言 作用:创建/删除/修改 库表结构
SHOW/USE/CREATE DATABASE/DROP DATABASE
CREATE TABLE tablename(
id int unsigned not null auto_increment comment '',
user_name varchar(20) not null comment '',
age tinyint unsigned not null comment '',
fee decimal(10,2) not null default 0.00 comment '用户余额',
created_at timestamp not null comment '注册时间',
primary key(id)
);
DESC tablename;
SHOW create table tablename;
DROP TABLE tablename;
ALTER TABLE tablename MODIFY user_name varchar(50) NOT NULL;
ALTER TABLE tablename ADD password CHAR(32) not null comment '用户密码' AFTER user_name;
ALTER TABLE tablename DROP password;
ALTER TABLE tablename RENAME to tablename1;
DML 数据操作语言 作用:增删改表的记录
INSERT INTO tablename (col1,col2) VALUES(val1,val2);
UPDATE tablename set user_name = 'new' where id = 1;
DELETE FROM tablename where id = 1;
TRACATE tablename; #清空表数据,并将id从头开始计算;delete不会使id清空
DCL 数据控制语言 作用:用户的创建以及授权
线上是不允许使用超级用户ROOT的
MariaDB [mysql]> select user,host from user;
+------+-----------------------+
| user | host |
+------+-----------------------+
| root | 127.0.0.1 |
| root | ::1 | #IPV6
| | localhost |
| root | localhost |
| | localhost.localdomain |
| root | localhost.localdomain |
- 修改密码:
方式一:update user set password=PASSWORD(‘123456’) WHERE user = ‘root’;
flush privileges;
方式二:mysqladmin -uroot -h127.0.0.1 -p123456 password 123
启动时不需要密码可以使用参数:–skip-grant-tables
- 创建用户
create user ‘test’@‘192.168.252.138’ identified by ‘123456’; #’%‘表示所有ip都可以登录(不安全)
flush privileges;
grant select,update,insert,delete on shop.* to ‘test’@’%’;
flush privileges;
- 撤销权限
REVOKE select on shop.* from ‘test’@’%’;
flush privileges;
- 所有权限*.*
所有的数据库,用*.* 所有的权限就用ALL或者ALL PRIVILEGES
grant all privileges on . to ‘test1’@‘192.168.252.138’; #相当于又创建了一个root用户
flush privileges;
- 创建用户兼授权
grant select,delete,update,insert on shop.* to ‘test3’@’%’ identified by ‘123456’;
flush privileges;
- 查看权限
SHOW GRANTS FOR ‘test’@’%’;
- 删除用户
DROP USER ‘test2’@’%’;
DQL 数据查询语言 作用:查询数据
SELECT col1,col2 FROM tablename [WHERE condition];
SELECT distinct col1 FROM tablename [WHERE condition];
SELECT concat(user_name,age) as name_age from tablename;
SELECT concat_ws('==',user_name,age) as name_age from tablename;
- 排列
SELECT * FROM tablename ORDER BY colname ASC/DESC;
- 聚合函数
COUNT() SUM(age) AVG(fee) MAX() MIN(*)
- 分组查询
SELECT count() FROM tablename GROUP BY sex (按性别分组)
SELECT count() FROM tablename GROUP BY sex having count(*) > 2;
- 连接查询
- 内连接查询(两者等价,两种形式)
select A.name,B.mark from student as A, mark as B where A.id = B.stu_id;
select A.name,B.mark from student as A inner join mark as B where A.id = B.stu_id; - 左连接查询(left join … on …,以左边的表为基础)
select A.name,B.mark from student as A left join mark as B on A.id = B.stu_id;
- 右连接
select A.name,B.mark from student as A left join mark as B on A.id = B.stu_id;
- 联合查询 列数一致
select name from student union all select mark from mark;
select * from student where id = 2 union all select * from student where id = 5;
- 子查询
select * from student where id in (select stu_id from mark);
- 限制查询条数
SELECT * FROM student LIMIT 3,2;
- 导出:
mysqldump -uroot -p123456 shop tablename > tablename.sql;
存储引擎
存储引擎就是如何存储数据,如何为存储的数据建立索引和如何更新、查询数据,因为在关系数据库中数据的存储是以表的形式存储的,所以存储引擎也可以称为表类型。
存储引擎 | 描述 |
---|---|
MyISAM | 全文索引(full text) 不支持事务 表级锁 崩溃恢复支持不好 |
InnoDB | 支持事务 不支持全文索引 5.6版本后开始支持(默认) 速度快 行级锁 崩溃恢复 |
BLACKHOLE | |
CSV | |
MEMORY | |
ARCHIVE |
默认的存储引擎:default-storage-engine=INNODB
- 查询/更改所有表
SHOW TABLE STATUS;
SHOW ENGINES;
ALTER table test engine=MyISAM;
字符集
- 查看字符集:SHOW CHARACTER SET;
- 显示乱码问题
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
connection、client和result字符集必须一致,并且和xshell的编码格式一致,显示才会正常。
- mariadb配置文件永久修改:
[client.cnf][client]default-character-set=utf8
[server.cnf][mysqld]character-set-server=utf8 - 字符集校对
校对规则是定义了比较字符串的方式,解决排序和字符分组的问题。
show CHARACTER SET;
UTF8默认的校对字符集是utf8_general_ci
SHOW TABLE STATUS;
关于int char varchar
汉子存储:多个字节
GBK存储 2个字节
UTF8存储 3个字节
-
INT(11): 11只有在zerofill设置的情况下才有用,用于补齐
alter table tablename modify num int(6) zerofill unsigned; -
CHAR(3): 3表示可存储的字符的长度,比如’123’,‘我是谁’
char:默认是1个字符的长度
查看字节长度:length(name)
查看字符长度:char_length(name)
CHAR 0-255字节, 这里的255指的是字符长度 -
VARCHAR(N):同CHAR
VARCHAR 0-65535字节 -
sql_mode模式
模式为STRICT_TRANS_TABLES时,对长度严格限制,插入失败。
模式为ANSI时,对长度比较宽松,超过长度会有告警。
事务控制语言 DTL
一个sql语句就是一个事务
事务可以保证一组SQL语句要么都成功要么都失败
默认自动提交
使用
start transaction;
update user set fee = 3000 where id = 1;
update user set fee = 3000 where id = 2;
rollback; 回滚
commit; 提交
原则:
1.原子性
2.一致性
3.隐藏性:如果多个事务同时并发执行,但每个事务就像各自独立执行一样
4.持久性:一个事务执行成功,则对数据来说应该是一个明确的硬盘数据更改(而不仅仅是内存中的变化)
自动提交autocommit
如果autocommit=ON 自动提交
如果autocommit=OFF 需要手动commit才能执行成功
MariaDB [bank]> show variables like ‘%autocommit%’;
±--------------±------+
| Variable_name | Value |
±--------------±------+
| autocommit | ON |
±--------------±------+
- 存储引擎
MyISAM存储引擎不支持事务
InnoDB支持事务
存储过程函数
存储过程:是一组为了完成特定功能的SQL语句集合,经编译后存储在数据库中,用户通过指定存储过程的名称并给出参数来执行。
- 与函数的区别:
- 函数必须有返回值,而存储过程没有,
- 存储过程的参数可以是IN,OUT,INOUT类型,而函数参数只能是IN类型
- 查看存储过程:
SHOW {PROCEDURE|FUNCTION} STATUS [LIKE ‘pattern’]
SHOW CREATE {PROCEDURE|FUNCTION} sp_name;
通过查看infomation_schema.Routines了解存储过程和函数信息:
select * from information_schema.routines where ROUTINE_NAME = ‘sp_name’\G;
CREATE PROCEDURE get_cores_v(IN sid INT, OUT core INT)
BEGIN
SELECT AVG(cores) INTO core from student where id > sid;
END //
CREATE PROCEDURE get_cores_b(IN sid INT, OUT count INT)
BEGIN
SELECT * from student where id > sid;
SELECT FOUND_ROWS() INTO count; #获取满足条件的行数
END //
运行结果:
MariaDB [shop]> call get_cores_v(3,@cc)//
Query OK, 1 row affected (0.00 sec)
MariaDB [shop]> select @cc//
±-----+
| @cc |
±-----+
| 506 |
±-----+
- characteristic特征值:
- LANGUAGE SQL 系统默认
- [NOT]DETERMINISTIC 确定的,即每次输入一样输出也会一样;非确定的(默认)
- {CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA}
CONTAINS SQL:子程序不包含读或写数据的语句(默认)
NO SQL:子程序不包含SQL语句
READS SQL DATA: 子程序包含写数据的语句 - SQL SECURITY { DEFINER | INVOKER} 指定子程序是用创建子程序者的许可来执行,还是使用调用者的许可来执行。默认DEFINER
- COMMENT ‘string’:注释信息
(4)的用法:创建过程后;给普通用户赋予执行权限GRANT EXECUTE ON sakila.* TO ‘lisa’@‘localhost’;再执行,则SQL SECURITY INVOKER会被拒绝,SQL SECURITY DEFINER可以执行成功。
过程和函数的语法
- 变量的使用
DECLEAR var_name[,…] type [DEFAULT value]
eg:
DECLEAR last_month_start DATE;
变量赋值语法:
SET last_month_start = DATE_SUB(CURRENT_DATE(), INTERVAL 1MONTH);
或通过查询赋值:
SELECT col_name[,…] INTO var_name[,…] table_expr;
- 控制变量
IFNULL(expression_1,expression_2);
如果expression_1不为NULL,则IFNULL函数返回expression_1; 否则返回expression_2的结果。
CREATE FUNCTION get_avg_cores(ID INT)
RETURNS INT
DETERMINISTIC
READS SQL DATA
BEGIN
DECLARE v_core INT;
SELECT IFNULL(SUM(student.cores),0) INTO v_core FROM student where id >= ID;
RETURN v_core;
END
运行结果:
MariaDB [shop]> select get_avg_cores(3);//
±-----------------+
| get_avg_cores(3) |
±-----------------+
| 3528 |
±-----------------+
- 定义条件和处理
语法:
DECLARE condition_name CONDITION FOR condition_value
DECLARE handler_type HANDLER FOR condition_value[,…] sp_statement
condition_value: SQLSTATE [VALUE] sqlstate_value
handler_type: CONTINUE | EXIT | UNDO
condition_value: SQLSTATE[VALUE] sqlstate_value | condition_name | sqlwarning| NOT FOUND| SQLEXCEPTION
案例:对主键重进行处理:
CREATE PROCEDURE student_insert()
BEGIN
DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2 = 1; #继续进行处理
SET @x = 1;
INSERT INTO student(id, name, cores) VALUE (8, 'Test', '8');
SET @x = 2;
INSERT INTO student(id, name, cores) VALUE (1, 'Test', '1');
SET @x = 3;
END
结果:
MariaDB [shop]> select @x,@x2//
±-----±-----+
| @x | @x2 |
±-----±-----+
| 3 | 1 |
±-----±-----+
条件语句还可以写其他形式:
DECLARE CONTINUE HANDLER FOR 1062 SET @x2 = 1;
DECLARE DuplicateKey CONDITION FOR SQLSTATE ‘23000’;
DECLARE CONTINUE HANDLER FOR DuplicateKey SET @x2 = 1;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET @x2 = 1;
- 光标的使用
声明: DECLARE cursor_name CURSOR FOR select_statement;
OPEN光标: OPEN cursor_name;
FETCH光标: FETCH cursor_name INTO var_name[,var_name]…
CLOSE光标: CLOSE cursor_name;
CREATE PROCEDURE get_sum()
BEGIN
#变量和条件声明必须在前面,然后是光标的声明,最后才可以是处理程序的声明
DECLARE one_core INT;
DECLARE cursor_core cursor FOR select cores from student;
DECLARE EXIT HANDLER FOR NOT FOUND CLOSE cursor_core;
SET @sum_core = 0;
OPEN cursor_core;
REPEAT
FETCH cursor_core INTO one_core;
SET @sum_core = @sum_core + one_core;
UNTIL 0 END REPEAT;
CLOSE cursor_core;
END
结果:
MariaDB [shop]> select @sum_core//
±----------+
| @sum_core |
±----------+
| 3536 |
±----------+
1 row in set (0.00 sec)
- 流程控制
语句:IF, CASE, LOOP, LEAVE, ITERATE, REPEAT, WHILE
IF search_condition THEN statement_list
...
END IF
CASE case_value
WHEN when_value THEN statement_list
[WHEN when_value THEN statement_list]...
[ELSE statement_list]
END CASE
[begin_label:]LOOP
statement_list
END LOOP [end_label]
ITERATE语句:必须用在循环中,作用是跳过当前循环的剩下语句,直接进入下一轮循环
IF statement THEN
TERATE tag;
END IF
REPEAT语句:
[label]:REPEAT
statement_list
UNTIL search_condition
END REPEAT;
WHILE语句:
[begin_label]:WHILE search_condition DO
statement_list
END WHILE [end_label]
CREATE PROCEDURE insert_loop()
BEGIN
SET @x = 0;
tag:LOOP
SET @x = @x + 1;
IF @x = 50 THEN
LEAVE tag;
END IF ;
INSERT INTO t1(n) VALUES(0.21);
END LOOP tag;
END
结果:
MariaDB [shop]> select count() from t1 where n = 0.21;//
±---------+
| count() |
±---------+
| 49 |
±---------+
事件调度器
- 创建:
CREATE EVENT test_event_1
ON SCHEDULE
EVERY 5 SECOND
DO
INSERT INTO t1 values(0.22);
- 查看调度器状态:
MariaDB [shop]> show events\G //
*************************** 1. row ***************************
Db: shop
Name: test_event_1
Definer: root@localhost
Time zone: SYSTEM
Type: RECURRING
Execute at: NULL
Interval value: 5
Interval field: SECOND
Starts: 2019-04-28 17:44:24
Ends: NULL
Status: ENABLED
Originator: 0
character_set_client: utf8
collation_connection: utf8_general_ci
Database Collation: latin1_swedish_ci
1 row in set (0.00 sec)
- 打开调度器
MariaDB [shop]> show variables like '%scheduler%';//
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| event_scheduler | OFF |
+-----------------+-------+
1 row in set (0.01 sec)
MariaDB [shop]> set GLOBAL event_scheduler=ON//
Query OK, 0 rows affected (0.00 sec)
- 禁用或者删除EVENT:
alter event test_event_1 disable;
drop event test_event_1;
视图view
语法: create view 视图名[(col1, col2,…)] as select 语句
- 视图的使用:当做一个查询表来用
create view test_view(name,age) as select name,age from student where id = 2;
show create view test_view;
select name,age from test_view;
触发器:可以用于统计
- 语法:
create trigger 触发器名 after|before insert|update|delete on 表名 for each row
begin
SQL语句
end;
- 查看/删除
show create trigger delete_total_num;
DROP trigger delete_total_num;
示例:
CREATE TRIGGER insert_total_num
AFTER INSERT ON article
FOR EACH ROW
BEGIN
update total_num set num=num+1 where type = 1;
END;//
CREATE TRIGGER delete_total_num
AFTER DELETE ON article
FOR EACH ROW
BEGIN
update total_num set num=num-1 where type = 1;
END;//
数据的导入和导出
- mysqldump(速度快)
导出:mysqldump -uroot -p123 -h127.0.0.1 shop student > ss.sql
导入:mysql -uroot -h127.0.0.1 -p123 shop < ss.sql - 工具 navicate phpmyadmin(不推荐,不安全)
远程连接失败:防火墙关闭。systemctl stop firewalld
测试端口:telnet 127.0.0.1 3306 - source命令导入
- 对于上亿条的数据,使用xtrabackdump(一般使用不到)
索引
- 添加索引:
alter table tablename add index/unique/fulltext 索引名
- 删除索引:
alter table tablename drop index 索引名
- 查看表索引:
show index from tablename;
注意:索引在提供查找速度的同时,降低增删改的速度。
- 分类:
普通索引:key/index(字段名1,字段名2,…)
唯一索引:unique key(字段名1,字段名2,…)不允许重复
主键索引:primary key(字段名1,字段名2,…)
全文索引: fulltext(字段名1,字段名2,…)- 只有MyISAM支持;InnoDB不支持,Innodb会报错:The used table type doesn’t support FULLTEXT indexes
- 解决搜索时模糊查询的问题,例如:
select * from account where match(passport) against(‘bao850305’);
select * from account where passport like ‘%bao850305%’; #耗时较长- 缺点:只支持英文;对于中文需要每个汉字之间以空格分开
- 外键约束:foreign key(字段) REFERENCES 表名(字段名) innodb支持
- 作用:stu_id作为student的外键,如果student表中id不存在,则mark插入失败
- 创建示例
CREATE TABLE
mark
(
id
int(10) unsigned NOT NULL AUTO_INCREMENT,
mark
int(20) unsigned NOT NULL,
stu_id
int(10) unsigned NOT NULL,
PRIMARY KEY (id
),
foreign key(stu_id) references student(id)
);
SQL优化
- 查询/开启慢查询日志记录慢的语句
只有在查找问题的时候才会开启慢查询查找问题,否则慢查询会耗时,降低整个系统的性能。
show variables like ‘%slow%’ or ‘%long%’;
| slow_query_log | OFF #慢查询功能关闭
long_query_time | 10.0000 #表示如果耗时大于10s,则为慢查询
set global slow_query_log = ON;
set global slow_query_log = 2.00;
set profiling=ON;
MariaDB [shop]> show profiles;
±---------±-----------±----------------------------------+
| Query_ID | Duration | Query |
±---------±-----------±----------------------------------+
| 1 | 0.00041050 | show variables like ‘%profiling%’ |
MariaDB [shop]> show profile for query 1;
±---------------------±---------+
| Status | Duration |
±---------------------±---------+
| starting | 0.000042 |
| Opening tables | 0.000027 |
| After opening tables | 0.000003 |
…
| System lock | 0.000002 |
找到问题后解决时间较长的原因就可以了。
优化方法:增加索引,所有的where后面的字段都加索引。
- 关闭缓存
MariaDB [shop]> show variables like '%cache%'; +-------------------------------+----------------------+ | Variable_name | Value | +-------------------------------+----------------------+ ... | query_cache_size | 0 | | query_cache_type | ON | +-------------------------------+----------------------+ set global query_cache_size=1024000; MariaDB [shop]> show status like '%qcache_free%'; +--------------------+---------+ | Variable_name | Value | +--------------------+---------+ | Qcache_free_blocks | 1 | | Qcache_free_memory | 1006792 |
缓存功能,第一次慢,后面都比较快。
关闭缓存:query_cache_size=0,不会再出现第二次快的情况。
show profile for query N:
sending cached result to clinet耗时较多,表示从缓存中取数据。
waiting for query cache lock 如果时间较长,则表示写入缓存耗时较长,可关闭缓存。
- select *和select pid时间不一样
select pid的时间更短。(通过explain中的rows查看查效率) - 不要在语句中写入运算,比如pid+1=‘24’
- 不要使用左模糊查询
数据表的设计
-
第一范式(INF),原子性(不可再分)
即:表的列具有原子性,不可再分解,即列的信息,不能分解,只要数据库是关系型数据库,就自动的满足1NF。 -
第二范式(2NF)
是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF),第二范式要求数据库表中的每个实例或行必须可以被唯一地区分,为实现区分通常需要我们设计一个主键来实现(这里的主键不包含业务逻辑)
解释:每个表中都有一个id,这样表就不会重复 -
第三范式(3NF)
满足第三范式(3NF)必须先满足第二范式(2NF).简而言之,第三范式要求一个数据库表中不包含已在其他表中已包含的非主键字段。
即:表的信息,如果能够被推导出来,就不应该单独的设计一个字段来存放(能尽量外键join就用外键join).
很多时候,我们为了满足第三范式往往会把一张表分成多张表。另外:
范式部署绝对要求,有时候我们为了数据的使用方便,还会(需要)故意违反范式。
后续问题
- 数据库的其他函数
- 数据库优化
- 数据库的分区分表
- 数据库架构
- 读写分离以及实例