MySQL基础知识点集合

数据库MySQL

MySql常用命令(不区分大小写, ; 表示结束)

数据库中最基本的单元 --> 表 --> 表比较直观

\c 中止指令

  1. 登录mysql:
mysql -uroot -p
  1. 退出mysql:
exit;
  1. 创建一个数据库
mysql> create database ****;
  1. 查看数据库
mysql> show databases;
  1. 使用数据库
mysql> use ****;
  1. 查看数据表
mysql> show tables;
  1. 导入数据表,文件路径中不能包含中文
mysql> source 文件路径(如:D:\mysql\test.sql)
  1. 查看表结构
mysql> desc 表名

SQL语句的分类

分为:

  • DQL(Data Query Language):

     数据查询语言(凡是带有select关键字的都是查询语句)
     select...
    
  • DML(Data Mainipulation Language):

     数据操作语言(凡是对表当中的数据进行增删改的都是DML)
     insert,delete,update
    
  • DDL(Data Definition Language):

     数据表定义语言(主要操作表结构,不是表中的数据)
     	凡是带有create,drop,alter都是DDL
    
  • TCL(Transactional Control Langguage):

     事务控制语言
     	事务提交->commit,事务回滚->rollback
    
  • DCL(Data Control Language):

     数据控制语言
     	如:授权grant、撤销权限revoke
    

查询语句

  • 简单表查询:
    *查询 -> 效率低、可读性差,实际开发中不建议
selsec * from 表名
  • 查询各别字段,select后可以跟着字段名或者字面量
selsec 字段名,字段名 from 表名
selsec "字面量" from 表名
  • 给查询的关键字取别名 -> as,as关键字也可以省略
    不会修改表中的字段名
select 字段名,字段名 as 别名 from 表名
select 字段名,字段名 别名 from 表名	//加空格
select 字段名,字段名 '别名' from 表名	//若别名中有空格可以使用,加''
  • 字段可以使用数学表达式,如:
select name,i*12 '计数' from table 
  • 条件查询
select 
	name1,name2,name3, .. 
from
	表名
where 
	条件;

条件类型

  • 不等于 --> != ,<>

  • select sal from tabl where sal != 300;

  • select sal from tabl where <> 300;

  • 等于 --> =

    • select sal from tab where sal = 200;
  • 介于两个值之间 --> between … and … --> 必需遵循左小右大

    • select sal from tab where sal between 100 and 200;
  • 查询为空的值 --> is null,不为空 --> not is null, null不能使用null衡量

    • select name from tab where name is null;
    • select name from tab where name not is null;
  • 并且 and

    • select sal,name from tab where sal > 10 and name = '张';
  • 或者 or

    • select empo from tabl where empo = '焊工' or empo = ‘电工’;
    • and 和 or 同时出现的话,优先级 and 大于 or,可以使用‘小括号()‘来规定
  • 包含 in ,不是区间,in里面是具体的值,相当于多个or
    not in 不包含

    • select sal from tab where sal in (100,500,200);
    • select sal from tab where sal not in (100,500,200);
  • like 模糊查询,支持 %_ 匹配,% 匹配任意多个字符,_任意一个字符,如:

------------------------- % 的使用------------------------------------
//找出名字 name 中包含 ma 的值
select name from tab where name like '%ma%';
//找出名字 name 以k 结尾的
select name from tab where name like 'k%';
//找出名字 name 以bg 开头的
select name from tab where name like '%bg';
------------------------- _ 的使用------------------------------------
//查找第二个字母是 s 的名字name 
select name from tab where name like '_s%';
//查找第三个字母是 t 的名字name 
select name from tab where name like '__t%';

//找出name中带有 符号 _ 的值,要使用 \_ 进行转义
select name from tab where name like '%\_%';

排序(order by)

  • 排序 --> order by ,默认升序
    • select name,sal from tab order by sal;
    • 指定降序 --> desc
      • select name,sal from tab order by sal desc;
    • 指定升序 --> asc (默认)
      • select name,sal from tab order by sal asc;
    • 多条件排序,如 先根据sal升序,再根据name升序排序, sal asc相等才能执行name asc
      • select name,sal from tab order by sal asc , name asc;

以上综合使用

select 
	....
from
	....
where
	....
order by
	...

各关键字的执行顺序:
第一步:from ,第二步:where,第三步:select,第四步:order by (排序总是最后一步)
例如:找出工资在1250到3000之间的员工信息,要求按照薪资的降序排列

select 
	name,sal
from
	tab
where
	sal between 1250 and 3000
order by
	sal desc;

数据处理函数

数据处理函数又称为单行处理函数
单行处理函数的特点:一个输入对应一个输出
多行处理函数的特点:多个输入,对应一个输出

单行处理函数

  1. 常见的单行处理函数:
- lower 转换小写
- upper 转换大写
- substr 取子串,substr(字符串,起始下标,截取长度),起始下标从1开始
- length 计算长度
- concat 字符串拼接
- trim 去空格
- str_to_date 将字符串转日期,将varchar类型转为data类型
- date_format 格式化日期,将data类型转换为具有一定格式的varchar类型
- format	设置千分位
- round 四舍五入
- rand() 生成随机数
- ifnull 可以将null转换成一个具体的值 --> ifnull(数据,被当作哪个值),**null参数数学运算,输出结果都为null**
- case...when...then...when...then...else...end 当什么时候做什么(不修改数据库,只是操作查询结果)

举个例子:

//lower 转换小写
Select lower(name) from tab;
//upper 转换大写
Select upper(name) from tab;
//concat 字符串拼接
select concat(name,sal) from tab;
//length 取长度
select length(name) from tab;
// trim 去空格
select name from tab where name = trim('   tree');
// round 四舍五入,0保留整数,-1保留到十位
select round(sal,0) from tab;
//ifnull(数据,被当作哪个值),计算年薪
select (sal + ifnull(emp,0))*12 from tab;

//case...when...then...when...then...else...end,当员工的工作岗位是MANGER时工资上调10%,为SAILSMAN时,工资上调50%,其他正常
select 
	name,
	job,
	(case job when 'MANGER' then sal*1.1 when 'SAILSMAN' then 	sal*1.5 else sal end) as newsal 
from 
	tab;

------------------稍微整合一下---------------------------
//首字母大写
select concat(upper(substr(name,1,1)),substr(name,2,length(name) - 1)) as result from tab;

str_to_date(‘字符日期’,‘日期格式’)

mysql的日期格式
%Y 年
%m 月
%d 日
%h 时
%i 分
%s 秒
insert into t_user(id,name,birth) values(01,'jack',str_to_date('01-2-1999','%d-%m-%Y'));

date_format(日期类型数据,‘日期格式’)

select id, name, date_format(birth,'%m/%d/%Y') as birth from t_user;

多行处理函数(分组函数)

多行处理函数的特点:输入多行,最终输出一行

  • count 计数
  • sum 求和
  • sum 平均数
  • max 最大值
  • min 最小值

注意:

  1. 分组函数在使用的时候必须先分组,然后才能使用。如果没有对数据进行分组,整张表 默认 为一组。
  2. 分组函数不需要提前对NULL进行处理,自动忽略NULL
  3. 所有的分组函数可以组合起来一起使用
  4. 分组函数中不能直接使用where,只能是having

分组查询

在实际应用中,可能需要先进行分组,然后对每一组的数据进行操作,这时需要使用到分组查询。

select
	...
from
	...
where
	...
group by
	...
order by
	...

执行顺序:from --> where --> group by --> select --> order by

为什么分组函数不能直接使用在where后面?

因为分组函数在使用的时候必须先分组在使用,where执行的时候,还没有分组。所以where后面不能出现分组函数。

使用having可以对分完组之后的数据进行进一步过滤,having不能单独使用,having不能代替where,having必须和group by联合使用

重点结论:
在一条select语句当中,如果有group by语句的话,select后面自能跟:参加分组的字段,以及分组函数,其他的一律不能跟。

  • 例题:
    • 找出每个部门,不同工作岗位的最高薪资??
//技巧:两个字段联合成1个字段来看
select depton,job,max(sal) from tab group by depton,job;
	 -  找出每个部门最高薪资,要求显示最高薪资大于3000的??
//写法一:使用having,效率较低
select depton,sal from tab group by depton having max(sal) > 3000;

//写法二:使用where,where中不能使用分组函数
select depton,max(sal) from tab where sal > 3000 group by depton;

/**
*where和having,在where能够实现的情况下,首选where
*/
 -  找出每个部门平均薪资,要求显示平均薪资大于2500??
//在where无法实现的情况下,才使用having
select depton,avg(sal) from tab group by depton having avg(sal) > 2500;

大总结

查询语句格式顺序如下:

select 
	...
from
	... 
where
	...
group by
	...
having
	...
order by
	...
- 执行顺序:from --> where --> group by --> having --> select --> order by
  • 例题:
    • 找出每个岗位的平均薪资,要求显示平均薪资大于1500的,除MANAGER之外,要求按照平均薪资降序显示 ??
select 
	job,avg(sal) as avgSal
from 
	tab 
where 
	job <> 'MANAGER' 
group by 
	job 
having 
	avg(sal) > 1500 
order by 
	avgSal desc;

distinct 关键字

distinct --> 把查询结果,去除重复记录,只能出现在所有字段最前端

//distinct在job和name两个字段之前,表示将两个字段联合起来去重
select distinct job,name from tab;

表连接查询

跨表查询,多张表联合起来查询数据

连接查询分类

根据表连接的方式分类:

  • 内连接
    • 等值连接
    • 非等值连接
    • 自连接
  • 外连接
    • 左外连接(左连接)
    • 右外连接(右连接)
  • 全连接

两张表连接没有任何条件限制:
select dname,ename from etab,dtab;
当两张表进行连接查询,没有任何条件限制的时候,最终查询结果条数,是两张表条数的乘积,这种现象称为笛卡尔现象
解决笛卡尔现象,查询次数没有减少。
select dname,ename from etab,dtab where etab.ename = dtab.dname;
表起别名,很重要,效率问题。
select d.dname, e.ename from etab e, dtab d where e.ename = d.dname;
注意:
通过笛卡尔积现象得出,表的连接次数越多效率越低,尽量避免表的连接次数。

内连接

A、B 两种表没有主次关系

等值连接

例题:查询每个员工所在部门名称,显示员工名和部门名?

//SQL92语法,结构不清晰,和后期进一步筛选条件,都放在了where后面。
select 
	e.name, d.dname 
from 
	etab e, dtab d 
where 
	e.depton = d.depton and 后面加条件;

//SQL99语法
select 
	e.name,d.dname 
from 
	etab e 
inner join 
	dtab d 
on 
	e.depton = d.depton;

SQL99语法,表连接的条件是独立的,连接后,如果需要进一步筛选,再往后继续加where

//inner可以省略,可读性更好
select 
	...
from 
	a
inner join 
	b
on 
	a和b的连接条件
where
	筛选条件;

非等值连接

  • 条件不是一个等量关系,称为非等值连接。

例题:找出每个员工的薪资登记,要求显示员工名、薪资、薪资等级??

select
	e.ename ,e.sal ,s.grade
from 
	etab e
join
	stab s
on 
	e.sal between s.losal and s.hisal;

自连接

例题:查询员工的上级领导,要求显示员工名和对应的领导名??(员工信息与领导信息都存在员工表中)

 - 技巧:一张表看成两张表。
select 
	e.name as '员工名', b.name as '领导名'
from 
	emp e
join 
	emp b
on 
	e.mgr = b.empo;	//员工的领导编号 = 领导的员工编号

外连接

内连接的特点:完全能够匹配上这个条件的数据查询出来。
外连接特点:未匹配到的数据也可以查询出来。

right 代表:表示将join关键 右边 的这张表看成 主表,主要为了将这张表的数据 全部查出来,捎带着关联查询左边的表。
在外连接当中,两张表,产生了主次关系。
left 同理,左边 主表 全部查出来

-----------------------右连接right-----------------------------
//outer 可省略,带着可读性强
select 
	e.ename, d.dname
from 
	etab e right outer join dtab d
on 
	e.depton = d.depton;
	
-----------------------左连接left-----------------------------
//outer 可省略
select 
	e.ename, d.dname
from 
	etab e left join dtab d
on 
	e.depton = d.depton;

带有right的是右外连接,又称为右连接。
带有left的是左外连接,又称为左连接。
任何一个右连接都有左外连接的写法。
任何一个左外连接都有右外连接的写法。

外连接的查询结果条数一定大于内连接的查询结果条数。

  • 例题:查询每个员工的上级领导,要求显示所有员工的名字和领导名??
select 
	a.ename as '员工名' ,b.ename as '领导名‘
from 
	etab a
left join 
	etab b
on 
	a.mgr = b.empno; 

三张表、四张表的连接方式

一条SQL中 内连接外连接 可以混合使用。

select 
	...
from 
	a
join
	b
on
	//a和b 的连接条件
join
	c
on
	//a和c 的连接条件
join
	d
on
	//a和d 的连接条件
  • 例题:找出每个员工的部门名称以及工资等级,要求显示员工名、部门名、薪资、薪资等级??
select 
	e.ename,e.sal,d.dname,s.grade
from
	emp e
join
	dept d
on
	e.deptno = d.deptno
join 
	salgrade s
on
	e.sal between s.losal and s.hisal;
  • 例题:找出每个员工的部门名称以及工资等级,还有上级领导,要求显示员工名、领导名、部门名、薪资、薪资等级??
select 
	e.ename, e.sal, d.dname, s.grade, l.ename
from
	emp e
join
	dept d
on
	e.deptno = d.deptno
join 
	salgrade s
on
	e.sal between s.losal and s.hisal
left join 
	emp l
on
	e.mgr = l.empno;

子查询

  • 什么是子查询?
    select语句中嵌套select语句,被嵌套的select语句成为子查询。

子查询都可以出现在哪里??

select 	
	...(select)..
from
	...(select)..
where
	...(select)..

where语句中的子查询

  • 例题:找出比最低工资高的员工姓名和工资??
//第一步,查询最低工资是多少
select min(sal) from emp;
//第二步,找出>800的
select ename,sal,from emp where sal > 800;
 //第三步,合并
 select ename,sal from emp where sal > (select min(sal) from emp);

from语句中的子查询

- 注意:from后面的子查询,可以将子查询的查询结果当作一张临时表。
  • 例题:找出每个岗位的平均工资的薪资等级??
//先查询出每个岗位的平均工资
select job ,avg(sal) as avgsal from emp group by job;

//将上面查询出的结果看作一张 表t,与 薪资表salgrade 进行连接查询
select 
	t.*, s.grade
from 
	(select job ,avg(sal) as avgsal from emp group by job) t
join
	salgrade s
on
	t.avgsal between s.losal and s.hisal;

select中的子查询(了解即可)

注意:select后面的子查询只能一次返回一条结果,多于一条,就报错。

  • 例题: 找出每个员工的部门名称,要求显示员工名,部门名??
select
	e.ename, (select d.name from dept d where e.deptno = d.deptno) as dname
from
	emp e;

union 合并查询结果集

union的效率更高一些,对于表连接来说,每连接一次新表,则匹配的次数满足笛卡尔积,成倍的翻。
但是union可以减少匹配的次数。在减少匹配次数的情况下,还可以完成两个结果集的拼接。

  • 例题:查询工作岗位是MANAGER和SALESMAN的员工??
select ename, job from emp where job = 'MANAGER';
union
select ename, job from emp where job = 'SALESMAN';
  • 注意:
    • union在进行结果集的合并的时候,要求结果集的列数相同
    • 结果集合并时列和列的数据类型也要相同(MySQL中不报错,Oracle中会报错)

limit(重点)

- limit作用:将查询结果集的一部分取出来,通常使用在分页查询当中。
limit怎么使用:
完整用法:limit startIndex length
startIndex是起始下标默认从0开始,length 是长度
缺省用法:limit 5; 取前5条数据
  • 例题:按照薪资降序,取出排名在前5名的员工?
select 
	ename.sal
from 
	emp
order by
	sal desc
limit 0,5;
  • 注意:limit是在order by 之后执行的!!!!

  • 例题:取出工资排名在3-5名的员工???

select
	ename, sal
from 
	emp 
order by
	sal desc
limit 
	2,3;

分页

每页显示3条记录
第一页:limit 0,3
第二页:limit 3,3
第三页:limit 6,3
第四页:limit 9,3
每页显示pageSize条记录
第pageNo页:limit n, pageSize
n = (pageNo - 1) * pageSize

关于以上SQL语句的总结

select 
	...
from 
	...
where
	...
group by
	...
having
	...
order by 
	...
limit
	...

执行顺序:
from --> where --> group by --> having --> select -->order by --> limit

创建表(create)

建表的语法格式

create table 表名(
	字段名1 数据类型,
	字段名2 数据类型,
	字段名3 数据类型
);
  • 表名:建议以t_或者 tab1_开始,可读性强,见表名意
  • 所有标识符都是全部小写,单词和单词之间使用下划线进行衔接。

快速创建表

  • 原理:
    • 将一个查询结果当作一张新表创建。
    • 这个可以完成表的快速复制。
    • 表创建出来,同时表中的数据页存在。
create table emp2 as select * from emp;
create table emp2 as select ename,empon from emp where jop = 'MANEGER';

mysql中常见的数据类型

常见的数据类型:

  • varchar:可变长度的字符串,根据实际长度动态分配空间。
  • char:定长字符串,分配固定长度的空间存储数据,使用不当可能会导致空间浪费。
  • int:数字中的整数型,默认11。
  • bigint:数字中的长整型。
  • float:单精度浮点型。
  • double:双精度浮点型。
  • datetime:长日期,包括年月日时分秒信息,默认格式:%Y-%m-%d %h-%i-%s。
  • date:短日期,只包括年月日信息,默认格式:%Y-%m-%d。
  • clob:字符大对象,最多可存储4G的字符串。如存储长文章。超过255个字符的可使用clob来存储
  • blob:二进制大对象,专门用来存储图片、声音、视频等流媒体数据。往blob插入视频等数据,需要使用IO流。

案例:创建一个学生表

create table t_student(
	no int,
	name varchar(35),
	sex char(1), default 'm',
	age int(3),
	email varchar(255)
);

删除表(drop)

//直接删除,表不存在会报错
drop table t_student;

//存在,再删除
drop table if exists t_student;

插入数据(insert)

语法格式:
字段名和值要一一对应,数量对应,数据类型对应。

insert into 表名 (字段名1,字段名2,...) values(值1,值2,...);
- insert语句执行成功,必会多一条数据。
- 前面字段名都省略,等于都写上,后面所有值也要都写上 `insert into t_student values(2,'jack','m',20,'123@qq.com');`
  • 一次插入多条记录
insert into t_user(id,name,birth) values
(01,'jack',now()),
(02,'async',now()),
(03,'luccy',now());

插入日期格式的数据

str_to_date(‘字符日期’,‘日期格式’)

mysql的日期格式
%Y 年
%m 月
%d 日
%h 时
%i 分
%s 秒
insert into t_user(id,name,birth) values(01,'jack',str_to_date('01-2-1999','%d-%m-%Y'));

date_format(日期类型数据,‘日期格式’)

select id, name, date_format(birth,'%m/%d/%Y') as birth from t_user;

使用mysql函数获取系统当前时间:

  • now(),获取的时间带有,时分秒信息,是datetime类型。

修改(update)

  • 没有条件限制会导致所有数据更新。

语法格式:

update 表名 set 字段名1=值1,字段名2=值2,... where 条件;

// 例子
update t_student set name = '张三', birth = '2000-10-11', creat_time = now() where no = 2;

删除数据(delete)

  • 没有 where 条件,表中所有数据会全部删除。

语法格式:

delete from 表名 where 条件;

//例子
delete from t_student where np = 2;
  • delete删除的原理
    • 表中的数据被删除了,但是这个数据在硬盘上的真实存储空间不会被释放!!
    • 优点:支持回滚,后悔了可以在回复
    • 缺点:删除效率较低

回滚操作:

start transaction;	//开启事务
delete from dept_bak;	//删除数据
rollback;	//回滚恢复数据
  • truncate语句删除数据原理
    • 效率比较高,表被一次截断,物理删除
    • 删除表中数据,表还在
    • 缺点:不支持回滚
    • 优点:快速
//用法:
truncate table dept_bak;

约束(constraint)重点

在创建的时候,我们可以给表中的字段加上一些约束,来保证这个表中数据的完整性、有效性!

  • 常见约束:
    • 非空约束:not null
    • 唯一性约束:unique
    • 主键约束:primary key (简称PK)
    • 外键约束:foreign key(简称FK)
    • 检查约束:check(mysql不支持,oracle支持)

非空约束 not null

非空约束not null约束的字段不能为NULL

create table t_vip(
	id int,
	name varchar(35) not null
);

唯一性约束 unique

唯一性约束unique约束的字段不能重复,但是可以为NULL。

create table t_vip(
	id int,
	name varchar(35) unique,
	email varchar(255)
);
  • 例题:要求name和email两个字段联合起来具有唯一性??
create table t_vip(
	id int,
	name varchar(35),
	email varchar(255),
	unique(name,email)
);

约束没有添加在列的后面,这种约束被称为表级约束。 需要给多个字段联合起来添加某一个约束的时候,需要使用表级约束。

unique和not null合用

在mysql中,某个字段同时被not nullunique同时约束,该字段自动变为主键字段(oracle中不一样)

create table v_vip(
	id int,
	name varchar(35) not null unique	//声明为主键PRI
);

主键约束(primary key)重点

  • 主键值是每一行记录的唯一标识。
  • 主键值是每一行记录的身份证号!!!
  • 任何一张表都要有主键,没有主键,表无效。
  • 主键的特征: not null + unique (主键值不能为null ,且同时不能重复)

添加主键方法:

  • 一张表,主键约束只能有一个
//使用主键约束
create table v_vip(
//一个字段做主键,称为单一主键
	id int primary key,
	name varchar(35)
);

//使用表级约束
create table v_vip(
	id int,
	name varchar(35),
	primary key(id)
);

create table v_vip(
	id int,
	name varchar(35),
	email varchar(255),
	//id和name联合起来做主键,复合主键,开发中不建议使用。
	primary key(id,name)
);

主键除了,单一主键和复合主键之外,还可以这样进行分类?

  • 自然主键,主键值是一个自然数,和业务没有关系。(建议使用)
  • 业务主键,主键值和业务紧密关联,例如拿银行卡账号做主键值。

在mysql中,有一种机制,可以帮助我们自动维护一个主键值?

create table v_vip(
//设置主键值为自增,从1开始自增
	id int primary key auto_increment,
	name varchar(35),
	email varchar(255)
);

外键约束(foreign key,简称PK)重点

例:创建学生和班级信息表??

  • t_student表中的cno的值只能是t_class表中classno的值
//班级表,父表
create table t_class(
	classno int primary key,	//班级编号,主键
	classname varchar(255)		//班级名称
);

//学生信息表,子表
create table t_student(
	no int primary key auto_increment,	//学生编号,主键
	name varchar(35),					//学生名称
	cno int,							//班级编号
	foreign key(cno) references t_class(classno)	//添加外键约束
);
  • 删除表的顺序
    - 先删子,在删父
  • 创建表的顺序
    - 先创建父,再创建子
  • 删除数据的顺序
    - 先删子,再删父
  • 插入数据的顺序
    - 先插入父,再插入子
  • 子表中的外键引用父表中的某个字段,被引用的字段不一定为主键,但至少具有unique约束。
  • 外键中的值可以为NULL。

存储引擎(了解)

  • 存储引擎是MySQL中特有的术语,其他数据库中没有。
  • 存储引擎是一个表存储/组织数据的方式。
  • 不同的存储引擎,表存储数据的方式不同。

给表添加指定的“存储引擎”

//查看表创建的结构
show create table t_student;

可以在建表的时候给表指定存储引擎

CREATE TABLE `user` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(20) NOT NULL,
  `password` varchar(20) NOT NULL,
  `gender` varchar(2) DEFAULT NULL,
  `email` varchar(50) DEFAULT NULL,
  `telephone` varchar(20) DEFAULT NULL,
  `introduce` varchar(100) DEFAULT NULL,
  `activeCode` varchar(50) DEFAULT NULL,
  `state` int(11) DEFAULT '0',
  `role` varchar(10) DEFAULT '普通用户',
  `registTime` timestamp(6) NULL DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4

在建表的时候可以在最后小括号的 “)” 的右边使用:

  • ENGINE来指定存储引擎

  • CHARSET来指定这张表的字符编码方式

    结论:

    • mysql默认的存储引擎是:InnoDB
    • mysql默认的字符集编码方式是: utf8

可以在建表的时候声明存储引擎:

create table t_table(
	name varchar(35) primary key,
	age int(3)
)engine=InnoDB default charset=gbk;

查看MySQL支持的存储引擎

根据数据的版本,支持的存储引擎会有不同。

show engines \G

mysql支持9大存储引擎:

*************************** 1. row ***************************
      Engine: MEMORY
     Support: YES
     Comment: Hash based, stored in memory, useful for temporary tables
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 2. row ***************************
      Engine: MRG_MYISAM
     Support: YES
     Comment: Collection of identical MyISAM tables
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 3. row ***************************
      Engine: CSV
     Support: YES
     Comment: CSV storage engine
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 4. row ***************************
      Engine: FEDERATED
     Support: NO
     Comment: Federated MySQL storage engine
Transactions: NULL
          XA: NULL
  Savepoints: NULL
*************************** 5. row ***************************
      Engine: PERFORMANCE_SCHEMA
     Support: YES
     Comment: Performance Schema
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 6. row ***************************
      Engine: MyISAM
     Support: YES
     Comment: MyISAM storage engine
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 7. row ***************************
      Engine: InnoDB
     Support: DEFAULT
     Comment: Supports transactions, row-level locking, and foreign keys
Transactions: YES
          XA: YES
  Savepoints: YES
*************************** 8. row ***************************
      Engine: BLACKHOLE
     Support: YES
     Comment: /dev/null storage engine (anything you write to it disappears)
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 9. row ***************************
      Engine: ARCHIVE
     Support: YES
     Comment: Archive storage engine
Transactions: NO
          XA: NO
  Savepoints: NO
9 rows in set (0.00 sec)

MySQL常见的存储引擎

MyISAM存储引擎:

管理的表具有以下特征

  • 使用三个文件表示每个表
    - 格式文件 - 存储表结构的定义(mytable.frm)
    - 数据文件 - 存储表行的内容(mytable.MYD)
    - 索引文件 - 存储表上索引(mytable.MYI):索引是一本书的目录,,缩小扫描范围,提高查询效率。

可被转换为压缩、、只读表来节省空间。 (优点)

提示:对于一张表来说,只要是主键,或者加有unique约束的字段上会自动创建索引。
MyISAM不支持事务,安全性低。

InnoDB存储引擎

mysql默认的存储引擎,同时也是一个重量级的存储引擎。
InnoDB支持事务,支持数据库崩溃后自动恢复机制。
InnoDB存储引擎最主要的特点是:非常安全。

管理的表具有一下主要特征:

  • 每一个 InnoDB表在数据库目录中以.frm格式文件表示
  • InnoDB表空间tablespace被用于存储表的内容(表空间是一个逻辑名称,表空间存储数据 + 索引)
  • 提供一组用来记录事务性活动的日志文件
  • 用COMMIT、SAVEPOINT及ROLLBACK支持事务处理
  • 提供全ACID兼容
  • 在MySQL服务器崩溃后提供自动恢复
  • 多版本(MVCC)和行级锁定
  • 支持外键及引用的完整性,包括联级删除和更新。

innoDB最大的优点支持事务,以保证数据安全。

MEMORY存储引擎

使用MEMORY存储引擎的表,其数据存储在内存中,且行的长度固定。

这两个特点使得MEMORY存储引擎非常快。

MEMORY 存储引擎管理的表具有一下特征:

  • 在数据库目录内,每个表均以.frm格式的文件表示。
  • 表数据及索引在存储在内存中(目的就是快,查询快)
  • 表级锁机制
  • 不能包含TEXT或BLOB字段。

MEMORY 存储索引以前被称为HEAP引擎。

事务(重点)

一个事务就是一个完整的业务逻辑。是一个最小的工作单元,不可再分。

  • 例如:银行转账,A向B转100,这是A账户扣除100,B账户加上100,这个操作要么同时成功,要么同时失败。

只有DML语句有事务一说,insert、update、delete,保证数据安全。

本质上,一个事务其实就是多条DML语句同时成功,或者同时失败。

事务(transaction)的实现

提交事务:
	-  清空事务性活动的日志文件,将数据全部彻底持久化到数据库表中。
	- 提交事务标志着,事务结束,并且是一种全部成功的结束。 
回滚事务:
	- 将之前所有的DML操作全部撤销,并且清空事务性活动的日志文件。
	- 回滚事务标志着,事务的结束,并且是一种全部失败的结束。

提交事务:commit; 语句

start transaction;	//开启事务
	.....//一系列DML语句
commit;	//提交事务

回滚事务:rollback; 语句 (回滚只能回滚带上一次提交点)

start transaction;	//开启事务
	.....//一系列DML语句
rollback;	//回滚事务

在mysql当中默认的事务行为:

  • 默认情况下,支持自动提交事务的。(自动提交)
  • 什么是自动提交?
    • 每执行一条DML语句,则提交一次!

关闭自动提交机制命令:

start transaction;

事务包括4个特性

  • 原子性
    - 说明事务是最小的工作单元,不可拆分。
  • 一致性
    - 所有事务要求,在同一个事务当中,所有操作必须同时成功,或者同时失败,以保证数据的一致性。
  • 隔离性
    - A事务和B事务之间具有一定的隔离。
  • 持久性
    - 事务最终结束的一个保障,事务提交,就相当于将没有保存到硬盘上的数据保存到硬盘上。

事务的隔离性

4个事务的隔离级别

  • 读未提交:read-uncommitted(最低的)
    • 事务A可以读取到事务B未提交的数据。脏读现象(Dirty-Read),一般都是理论上的。大多数数据库隔离级别都是二档起步。
    • 没提交就读取到
  • 读已提交:read-committed
    • 事务A只能读取到事务B提交后的数据。解决脏读,但不可重复读取数据
    • 不可重复读:事务开启后,第一次读取到的数据3条,当前事务还没有结束,可能第二次再读取的时候,读到的数据是4条,3不等于4,称为不可重复读取。
    • 这种隔离级别是比较真实的数据,每一次读到的数据是绝对的真实。oracle数据库默认的隔离级别是:read-committed
    • 提交之后才能读到
  • 可重复读:repeatable-read
    • 事务A开启后,不管多久,每次在事务A中读取到的数据都是一致的。即使事务B将数据已经修改,并且提交了,事务A读取到的数据还是没有发生改变。
    • 解决了不可重复读问题,可能会出现幻读,不够真实!
    • MySQL中默认的隔离级别,可重复读。
    • 提交之后也读不到,永远读取到的都是刚开启事务时的数据。
  • 序列化/串行化(最高的):serializable
    • 最高隔离级别,效率最低,解决了所有问题。
    • 表示事务排队,不能并发。
    • 每次读取到的数据都是最真实的,并且效率是最低的。

隔离级别验证

//查看隔离级别
SELECT @@tx_isolation;	//新版本已经弃用了
SELECT @@transaction_isolation;	//新版本使用这个查看,mysql8.0+

MySQL基础知识点集合

read-uncommitted

//设置事务的隔离级别
mysql> set global transaction isolation level read uncommitted;

//---------------------事务B操作--------------------------//
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into t_user(name) values('wangwu');
Query OK, 1 row affected (0.01 sec)

mysql> rollback;
Query OK, 0 rows affected (0.00 sec)

//---------------------事务A操作--------------------------//
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t_user;	//在事务B 操作事务未提交,就读取到数据
+--------+
| name   |
+--------+
| wangwu |
+--------+
1 row in set (0.00 sec)

mysql> select * from t_user;	//当事务B 执行rollback回滚事务后,事务A 中的数据就没了
Empty set (0.00 sec)

read-committed

mysql> set global transaction isolation level read committed;

//---------------------事务B 操作--------------------------//
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into t_user values('zhangsan');	//执行insert ,但未提交事务
Query OK, 1 row affected (0.00 sec)

mysql> commit;		//提交事务
Query OK, 0 rows affected (0.00 sec)

//---------------------事务A 操作--------------------------//
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t_user;	//事务B 执行insert之前
Empty set (0.00 sec)

mysql> select * from t_user;	//事务B 执行insert之后
Empty set (0.00 sec)

mysql> select * from t_user;	//事务B commit提交事务后,执行
+----------+
| name     |
+----------+
| zhangsan |
+----------+
1 row in set (0.00 sec)

repeatable-read

mysql> set global transaction isolation level repeatable read;

//---------------------事务B 操作--------------------------//
mysql> start transaction;	//开启事务
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t_user;	//先查询表中数据
+----------+
| name     |
+----------+
| zhangsan |
+----------+
1 row in set (0.00 sec)

//向t_user表中,插入3条数据
mysql> insert into t_user(name) values('jack'),('wangwu'),('daniu');	
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from t_user;
+----------+
| name     |
+----------+
| zhangsan |
| jack     |
| wangwu   |
| daniu    |
+----------+
4 rows in set (0.00 sec)

mysql> commit;		//提交事务
Query OK, 0 rows affected (0.00 sec)

//---------------------事务A 操作--------------------------//
mysql> start transaction;	//开启事务
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t_user;	//事务B,执行insert之前查询
+----------+
| name     |
+----------+
| zhangsan |
+----------+
1 row in set (0.00 sec)

mysql> select * from t_user;	//事务B,执行insert之后查询
+----------+
| name     |
+----------+
| zhangsan |
+----------+
1 row in set (0.00 sec)

mysql> select * from t_user;	//事务B,执行commit 提交事务后查询
+----------+
| name     |
+----------+
| zhangsan |
+----------+
1 row in set (0.00 sec)

serializable

mysql> set global transaction isolation level serializable;

//---------------------事务B 操作--------------------------//
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t_user;
+----------+
| name     |
+----------+
| zhangsan |
| jack     |
| wangwu   |
| daniu    |
+----------+
4 rows in set (0.00 sec)

//---------------------事务A 操作--------------------------//
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t_user;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql>_		//当事务B 的操作未提交commit时,事务A 的操作无法进行操作。

//当事务B 将事务提交commit后,事务A 才能继续执行。
+--------------------+
| name               |
+--------------------+
| zhangsan           |
| jack               |
| wangwu             |
| daniu              |
| serializableUser   |
| serializableUser22 |
+--------------------+
6 rows in set (0.00 sec)

索引(index)

索引是在数据库表的字段上添加的,是为了提高查询效率存在一种机制。
一张表的一个字段可以添加一个索引,当然,多个字段联合起来也可以添加索引。

Mysql在查询方面主要就两种方式:
全表扫描
根据索引检索

在MySQL数据库当中索引也需要排序,并且这个索引的排序和TressSet数据结构相同。TreeSet(TreeMap)底层是一个自平衡的二叉树! 在mysql当中索引是一个B-Tree数据结构。
遵循左小右大原则存放,采用中序遍历方式遍历取数据。

索引实现原理

缩小扫描范围,避免全表扫描。

提醒1:在任何数据库当中主键上都会自动添加索引对象,id字段上自动有索引。因为id是PK。另外在MySQL当中,一个字段上如果有unique约束的话,也会自动创建索引对象。
提醒2:在任何数据库当中,任何一张表的任何一条记录在硬盘上都有一个硬盘的物理存储编号。
提醒3:在mysql当中,索引是一个单独的对象,不同的存储引擎以不同的形式存在。在MyISAM存储引擎中,索引存储在一个.MYI文件中。在InnDB存储引擎中,索引存储在一个逻辑名称叫做tablespace的当中。在MEMORY存储引擎中,索引被存储在内存当中。不管索引存储在哪里,索引在mysql当中都是一个树的形势存在。(平衡二叉树:B-Tree)

举个例子:
MySQL基础知识点集合
MySQL基础知识点集合

添加索引条件:
	- 数据量庞大
	- 该字段经常出现在where后面,以条件的形式存在,也就是说这字段总是被扫描。
	- 该字段很少的DML操作,因为DML之后,索性需要重新排序。

建议不要随意添加索引,因为索引也需要维护,太多的话反而会降低系统的性能。
建议通过主键查询,通过unique约束的字段进行查询,效率比较高。

索引的创建和删除

//给emp表的ename字段添加索引,起名:emp_ename_index
create index emp_ename_index on emp(ename);

//删除索引
drop index emp_ename_index on emp;

查看索引

//使用explain 查看语句查询方式 
mysql> explain select * from user where email ='19747708@qq.com';
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | user  | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    5 |    20.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

rows=5扫描了5条记录,type=ALL,说明没有使用索引。

//创建索引
create index email_index on user(email);

//使用explain 查看语句查询方式
mysql> explain select * from user where email ='19747708@qq.com';
+----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key         | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | user  | NULL       | ref  | email_index   | email_index | 203     | const |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.01 sec)

rows=1扫描了1条记录,type=ref ,说明使用索引。

索引失效

情况1:
避免使用模糊查询的时候以“%”开始,这是一种优化策略。

mysql> explain select * from user where email like '%708';
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | user  | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    5 |    20.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

情况2:
使用or的时候会失效如果使用or那么要求两边的条件都要有索引,才会走索引,如果其中一边有一个字段没有索引,那么另外一个字段上的索引也会失效,所以不建议使用or。

mysql> explain select * from user where email = '19747708@qq.com' or telephone ='12345678911 ';
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | user  | NULL       | ALL  | email_index   | NULL | NULL    | NULL |    5 |    36.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

情况3:
使用复合索引的时候,没有使用左侧的列查找,索引失效。
复合索引:两个字段,或者更多的字段联合起来添加一个索引。

create index role_name on user(role,username);

//--------------左侧索引 role---------------------//
mysql> explain select * from user where role = '普通用户';
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key       | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | user  | NULL       | ref  | role_name     | role_name | 43      | const |    3 |   100.00 | NULL  |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

//--------------右侧索引 username-----------------//
mysql> explain select * from user where username = 'as123';
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | user  | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    5 |    20.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

情况4:
在where当中索引参加了数学运算,索引失效。

mysql> create index state_index on user(state);

//-------------未添加数学运算----------------//
mysql> explain select * from user where state = 1;
+----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key         | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | user  | NULL       | ref  | state_index   | state_index | 5       | const |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

//-------------添加数学运算----------------//
//索引 列 state参加数学运算
mysql> explain select * from user where state+1 = 1;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | user  | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    5 |   100.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

情况5:
在where当中索引使用了函数。

mysql> drop index role_name on user;
mysql> create index name_index on user(username);

//----------------------------------未添加函数---------------------------------//
mysql> explain select * from user where username = 'asd123';
+----+-------------+-------+------------+------+---------------+------------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key        | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | user  | NULL       | ref  | name_index    | name_index | 82      | const |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+------+---------------+------------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

//----------------------------------添加函数---------------------------------//
mysql> explain select * from user where lower(username) = 'asd123';
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | user  | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    5 |   100.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

索引分类

索引是各种数据库进行优化的重要手段。优化优先考虑索引。

  • 单一索引 :一个字段上添加索引。
  • 复合索引:两个字段或者更多的字段上添加索引。
  • 主键索引:主键上添加索引。
  • 唯一性索引:具有unique约束的字段上添加索引。
  • 注意:唯一性比较弱的字段上添加索引用处不大。

视图(view)

站在不同角度去看待同一份数据。

  • 可以面向视图对象进行 增删改查 ,对视图对象的 增删改查,会导致原表被操作。(通过操作视图,会影响到原表的数据)
  • 简化SQL语句,将复杂的SQL语句直接使用视图对象。
  • 使用视图的时候可以像使用tbale一样,视图也是存储在硬盘上,不会消失。

创建视图

  • 只有DQL语句才能以view的形式创建。
  • 可以对多表连接查询,创建视图
create view user2_view as select * from user;

删除视图

drop view user2_view;

操作视图

//对user2_view 视图进行插入操作
mysql> insert into user2_view(username,password,gender,email) values('jjjj','sss','m','123@qq.com');
Query OK, 1 row affected (0.00 sec)

//查询原表数据,发生改变
mysql> select * from user2;
+----+------------+----------+--------+--------------------+-------------+------------------+------------+-------+----------+----------------------------+
| id | username   | password | gender | email              | telephone   | introduce        | activeCode | state | role     | registTime                 |
+----+------------+----------+--------+--------------------+-------------+------------------+------------+-------+----------+----------------------------+
|  1 |            |          | NULL   | NULL               | NULL        | NULL             | NULL       |     0 | NULL     | 0000-00-00 00:00:00.000000 |
|  3 | as123      | 123456   | 男     | 1974708999@qq.com  | 17706058702 | fddfds           | NULL       |     0 | 普通用户 | 2020-06-13 00:00:00.000000 |
|  4 | sasassa123 | 654321   | 男     | 1974708999@163.com | 17706058703 | asdasff          | NULL       |     0 | 普通用户 | NULL                       |
|  5 | tti_12     | 987654   | 男     | 1421842575@12.com  | 12346789112 | 测试账户登录账号 | NULL       |     0 | 普通用户 | NULL                       |
|  6 | al_22      | 159753   | 男     | 1974708999@123.com | 12345678911 | 验证信息123      | NULL       |     1 | 超级用户 | NULL                       |
|  0 | jjjj       | sss      | m      | 123@qq.com         | NULL        | NULL             | NULL       |     0 | 普通用户 | NULL                       |
+----+------------+----------+--------+--------------------+-------------+------------------+------------+-------+----------+----------------------------+
6 rows in set (0.00 sec)

DBA常用命令(不常用):

重点掌握数据的导入导出(数据备份)

数据的导出:

  • 在windows的dos命令窗口中:
    mysqldump bjpowernode>D:\bjpowernode.sql -uroot -p123
    - 导出指定的表:mysqldump bjpowernode table>D:\bjpowernode.sql -uroot -p123
    MySQL基础知识点集合

数据导入

  • 需要先登录到mysql数据库服务器上。
  • 然后创建数据库:create database bjpowernode;
  • 使用数据库: use bjpowernode;
  • 然后初始化数据库:source D:\bjpowernode.sql

数据库设计范式

  • 第一范式:要求任何一张表必须有主键,每一个字段原子性不可再分。
  • 第二范式:建立在第一范式的基础上,要求所有非主键字段完全依赖主键。
  • 第三范式:建立在第二范式的基础上,要求所有非主键字段直接依赖主键。不要产生传递依赖。
  • 设计库表设计,遵循范式进行,可以避免表中数据的冗余,空间浪费。

第一范式

最核心,最重要的范式,所有表的设计都需要满足。
必须要有主键,并且每一个字段都是原子性不可拆分。
MySQL基础知识点集合

第二范式

建立在第一范式的基础上,要求所有非主键字段必须完全依赖主键,不要产生部分依赖。
多对多设计:多对多,三张表,关系表两个外键。
MySQL基础知识点集合MySQL基础知识点集合

第三范式

第三范式建立在第二范式的基础上,要求所有非主键字段必须直接依赖主键,不要产生传递依赖。

一对多设计:两张表,多的表加外键。
MySQL基础知识点集合MySQL基础知识点集合

总结表的设计

  • 多对多设计:多对多,三张表,关系表两个外键。
  • 一对多设计:两张表,多的表加外键。

在实际开发中,可能存在一张表字段太多,太庞大,这时候需要拆分表。

  • 一对一设计:一对一,外键唯一(FK+UNIQUE)
    MySQL基础知识点集合

总结:

  • 数据库设计三范式是理论上的。
  • 在MySQL当中,表和表之间连接次数越多,效率越低。(笛卡尔集)
  • 有时候可能存在冗余,但是为了减少表的连接次数,这样做也是合理的。并且对于开发人员来说,sql语句的编写难度也会降低。
上一篇:MySQL常用查询命令


下一篇:linux系统下查看svn服务是否启动,重启及设置开机重启