• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

MySQL入门详细

武飞扬头像
热爱编程的申同学
帮助1

目录

1、什么是数据库?

2、数据库的特点

3、数据库的分类

4、MySQL的登录和退出

4.1、MySQL的登录

5、SQL语句

5.1、什么是SQL?

5.2、通用语法

5.3、SQL语句的分类

6、操作数据库——DDL语言

7、操作表——DDL语言

7.1、数据类型

7.2、创建表

7.3、查询表

7.4、修改表

7.4.1、添加字段

7.4.2、修改列(字段)类型

7.4.3、修改列(字段)名和类型

7.4.4、删除指定列(字段)

7.4.5、查看表的字符集 

7.4.6、修改表字符集

7.4.7、修改表名

7.4.8、删除字段 

7.5、删除表

7.5.1、直接删除表

7.5.2、如果表存在就删除

8、约束

8.1、主键约束(primary key)

8.2、非空约束(not null)

8.3、唯一约束(unique)

8.4、外键约束(foreign key)

8.5、检查约束(check)

8.6、自增长(auto_increment)

8.7、缺省约束 默认值(default)

8.8、给表中字段添加约束

8.8.1、给表中字段添加主键约束

8.8.2、给表中字段添加非空约束

8.8.3、给表中字段添加唯一约束

8.8.4、给表中字段添加外键约束

8.8.5、删除表中的约束

9、数据操作DML

9.1、添加数据(insert into)

9.2、修改数据(update)

9.3、删除数据(delete)

10、数据查询DQL

10.1、单表查询

10.2、多表查询 

10.2.1、连表查询

10.2.2、子查询

11、用户权限DCL

11.1、创建用户

11.2、查看权限

11.3、授予权限

11.3.1、授予单个权限

11.3.2、授予多个权限

11.3.3、授予全部、指定的库和表

11.4、撤销授权

11.5、删除用户

11.6、密码管理

11.6.1、超级管理用户的密码修改

11.6.2、普通用户修改密码

12、三大范式

12.1、数据库第一范式

12.2、数据库第二范式

12.3、数据库第三范式

13、索引

14、横表和纵表的转换

14.1、纵表转横表

14.2、横表转纵表

15、悲观锁和乐观锁

15.1、行级锁

15.2、表级锁

16、MySQL引擎

16.1、Innodb引擎

16.2、MyIASM引擎

16.3、Innodb引擎、MyIASM引擎区别


1、什么是数据库?

数据库就是存储数据的仓库,其本质是一个文件系统,数据按照特定的格式将数据存储起来,用户可以对数据库中的数据进行增加,修改,删除及查询操作(CRUD)。

2、数据库的特点

1、持久化存储数据的。其实数据库就是一个文件系统 。
2、方便存储和管理数据、存储数据有一定的格式、行和列的格式
3、 使用了统一的方式操作数据库、使用图形界面的形式查看数据、使用sql语言进行查看或管理数据

3、数据库的分类

数据库分为关系型数据库和非关系型数据库,关系型数据库就是我们平常见到的二维表,就是典型的关系型数据库,非关系型数据库存放的数据没有什么联系,所以存储获取效率比较高,一般用于做缓存数据的Redis数据库就是这样的特点。

如下图,就是数据库分类汇总 

学新通

4、MySQL的登录和退出

4.1、MySQL的登录

本地登录

mysql -u用户名  -p密码        显示登录(密码会被显示出来)

mysql -u用户名  -p               隐式登录(不会显示密码  密码会被*替代 安全性高)

远程连接(指定ip登录)

mysql  -h主机地址   -u用户名  -p密码

4.2、MySQL的退出

三种方式:

exit或quit,或者直接点击DOS窗口的×号。

5、SQL语句

5.1、什么是SQL?

结构化查询语言(Structured Query Language)简称SQL,SQL语句就是对数据库进行操作的一种语言。 SQL是一套标准,所有的数据库厂商都实现了此标准;但是各自厂商在此标准上增加了特有的语句,这部分内容我们称为方言。

5.2、通用语法

1、SQL语句可以单行或多行书写,以分号结尾

  1.  
      select * from stu;
  2.  
      select 
  3.  
          *
  4.  
      FROM
  5.  
          stu;

2、可使用空格和缩进来增强语句的可读性。

3、MySQL 数据库的 SQL 语句不区分大小写(仅此于win系统),关键字建议使用大写,库名 表名 字段 别名 建议写小写,关键字建议大写: SHOW DATABASES CREATE。

4、3种注释
    单行注释: -- 注释内容(这种方式是通用的) 或 # 注释内容(mysql 特有) 
    多行注释: /* 注释 */

5.3、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 等
TCL(Transaction Control Language) 事务控制语言 用于控制数据库的事务操作,关键字; commit,savepoint,rollback等

6、操作数据库——DDL语言

创建数据库

create database 数据库名;

创建数据库,并指定字符集

create database 数据库名 character set 字符集名;

查询所有数据库名称

show databases;

查询某个数据库的字符集,查询某个数据库的创建语句及字符集

show create database 数据库名;

修改数据库的字符集

alter  database 数据库名 character set 字符集名;

删除数据库

drop database 数据库名;

查询当前正在使用的数据库名

select database();

使用数据库/进入数据库

use 数据库名;

7、操作表——DDL语言

7.1、数据类型

数据类型 说明
int 整数类型,例如 : age
double 小数类型,例如 : score double(5,2) 111.11
date 日期,只包含年月日,yyyy-MM-dd
datetime 日期,包含年月日时分秒 yyyy-MM-dd HH:mm:ss
timestamp 时间戳类型,包含年月日时分秒 yyyy-MM-dd HH:mm:ss 如果将来不给这个字段赋值,或赋值为null,则默认使用当前的系统时间,来自动赋值
varchar 可变字符 name varchar(20)
char 不可变字符 name varchar(20)

varchar与char的长度区别

1、varchar的可变是指长度可变,比如定义一个name varchar(20) 但是用户输入了一个"张三"只有两个长度,剩余的18个长度会被系统自动释放,varchar的长度也自动降为2个。

2、char是固定长度,比如定义一个name char(20) 但是用户同样输入一个"张三" 剩余的18个长度不会被释放,而是用留白符补全,char的长度还是20。

通过比较两者区别,可以得出:

varchar可以自动释放多余空间,避免了存储空间的浪费,一般开发推荐使用varchar。

char固定长度,但性能好,如果定义较大长度会造成储存空间浪费,一般会用于定义性别或者身份证号等固定长度的字段。

7.2、创建表

语法

  1.  
    create table 表名(
  2.  
    字段名 数据类型,
  3.  
    字段名 数据类型,
  4.  
    ....
  5.  
    字段名 数据类型
  6.  
    );

示例

  1.  
    create table student(
  2.  
    id int,
  3.  
    name varchar(32),
  4.  
    birthday date,
  5.  
    money double(5,2)
  6.  
    );

注意事项:最后一个字段定义不用写逗号,其余每一行都要写逗号。

7.3、查询表

查询某个数据库中所有的表

show tables;

 学新通

查询表结构

desc 表名;

学新通

7.4、修改表

column可以省略不写。

7.4.1、添加字段

alter table 表名 add 字段名 数据类型 约束;

默认在表中最后一列添加

alter table 表名 add column 字段名 类型 约束 默认值;

添加为第一行

alter table 表名 add column 字段名 类型 约束 默认值 first;

添加到指定字段之后

alter table 表名 add column 字段名 类型 约束 默认值 after 字段名;

实例

alter table student add height double(4,1);

7.4.2、修改列(字段)类型

alter table 表名 modify 列名 新类型;

实例

alter table student modify height int;

7.4.3、修改列(字段)名和类型

alter table 表名 change 旧列名 新列名 新类型;

实例

alter table student change height width double(4,1);

7.4.4、删除指定列(字段)

alter table 表名 drop 列名;

实例

alter table student drop width;

7.4.5、查看表的字符集 

show create table 表名;

7.4.6、修改表字符集

alter table 表名 charset 字符集名;

实例 

alter table student charset gbk;

7.4.7、修改表名

rename table 旧表名 to 新表名

实例

rename table student to teacher

7.4.8、删除字段 

alter table 表名 drop column 字段名;

7.5、删除表

7.5.1、直接删除表

drop table 表名;

7.5.2、如果表存在就删除

drop table if exists 表名;

8、约束

约束:规定,限制。限制表中的内容。需要满足一定的规则。数据库中的约束:限制列的内容。

意义:保证数据的有效性和完整性。可以确保数据库满足业务规则。

约束 说明
primary key 主键约束:非空且唯一
not null 非空约束 : 某一列的值不能为空
unique 唯一约束 : 某一列的值不能重复,但可以为空
auto_increment 自增器,每一次 1
foreign key 外键约束

8.1、主键约束(primary key)

限定当前字段中存放的值  非空且唯一,该约束,一张表只能存在一个。

说明:constraint 约束名   可以省略不写,这里只是给约束起名字,不影响约束创建。

列级约束(限定一个字段下的内容,声明字段时,在字段之后使用)

  1.  
    create table 表名(
  2.  
    字段 类型 primary key,
  3.  
    ....
  4.  
    字段 类型
  5.  
    );

表级约束 

  1.  
    create table 表名(
  2.  
    字段 类型,
  3.  
    字段 类型,
  4.  
    .....
  5.  
    字段 类型,
  6.  
    constraint 约束名 primary key(字段)
  7.  
    );

组合唯一 

  1.  
    create table 表名(
  2.  
    字段 类型,
  3.  
    字段 类型,
  4.  
    ....
  5.  
    字段 类型,
  6.  
    constraint 约束名 primary key(字段1,字段2)
  7.  
    );

8.2、非空约束(not null)

限定字段中不能存入空值  not null

  1.  
    create table 表名(
  2.  
    字段 类型 not null,
  3.  
    字段 类型 not null,
  4.  
    ....
  5.  
    字段 类型
  6.  
    );

8.3、唯一约束(unique)

限定字段中不能存入重复值,不包含null

列级约束

  1.  
    create table 表名(
  2.  
    字段名 类型 unique,
  3.  
    字段名 类型 unique,
  4.  
    ....
  5.  
    字段名 类型
  6.  
    );

表级约束

  1.  
    create table 表名(
  2.  
    字段 类型,
  3.  
    字段 类型,
  4.  
    .....
  5.  
    字段 类型,
  6.  
    constraint 约束名 unique(字段),
  7.  
    constraint 约束名 unique(字段)
  8.  
    );

组合唯一 

  1.  
    create table 表名(
  2.  
    字段 类型,
  3.  
    字段 类型,
  4.  
    ....
  5.  
    字段 类型,
  6.  
    constraint 约束名 unique(字段1,字段2)
  7.  
    );

8.4、外键约束(foreign key)

建立表与表之间的关系,限定从表中的外键字段的值只能依赖主表中的关联字段设置。

注意事项

1、添加数据时  必须先添加主表信息,后添加从表信息


2、删除数据时,必须先删除从表信息,再删除主表信息


3、外键字段的数据类型必须与主表关联字段类型一致


4、只能关联主表中的主键字段或被唯一约束的字段

列级约束(MySQL中失效)

  1.  
    create table 表名(
  2.  
     
  3.  
    字段 类型 references 主表名(字段),
  4.  
    ......
  5.  
    字段 类型
  6.  
     
  7.  
    );

表级约束

  1.  
    create table 表名(
  2.  
    字段 类型,
  3.  
    .........
  4.  
    字段 类型,
  5.  
    constraint 约束名 foreign key(字段),
  6.  
    references 主表名(字段)
  7.  
    );

组合外键

  1.  
    create table 表名(
  2.  
    字段 类型,
  3.  
    .........
  4.  
    字段 类型,
  5.  
    constraint 约束名 foreign key(字段1,字段2),
  6.  
    references 主表名(字段1,字段2)
  7.  
    );

8.5、检查约束(check)

给字段提供筛选条件。在mysql失效

列级约束

  1.  
    create table 表名(
  2.  
    字段 类型 check(字段条件),
  3.  
    字段 类型 check(字段条件and/or字段条件)
  4.  
     
  5.  
    );

实例

  1.  
    create table student(
  2.  
    id int,
  3.  
    name varchar(20),
  4.  
    sex char(1) check(sex='男' or sex='女')
  5.  
    );

表级约束

  1.  
    create table 表名(
  2.  
    字段 类型 ,
  3.  
    字段 类型 ,
  4.  
    ....
  5.  
    字段 类型,
  6.  
    constraint 约束名 check(字段条件)
  7.  
    );

组合约束

  1.  
    create table 表名(
  2.  
    字段 类型 ,
  3.  
    字段 类型 ,
  4.  
    ....
  5.  
    字段 类型,
  6.  
    constraint 约束名 check(字段条件1 and 字段条件2 or 字段条件3)
  7.  
    );

8.6、自增长(auto_increment)

产生一个每次增加1的序列

注意

1、自增长一张表中只能设置一个。
2、自增长只能设置在主键约束或者唯 一约束字段上。
3、该序列一旦使用会持续往后增长,不会自动回到之前的序号。

  1.  
    create table 表名(
  2.  
    字段 类型 primary key auto_increment,
  3.  
    .......
  4.  
    字段 类型
  5.  
    );

8.7、缺省约束 默认值(default)

未给字段输入值时,使用默认值填充

  1.  
    create table 表名(
  2.  
    字段 类型 default 值,
  3.  
    字段 类型 default 值,
  4.  
    .....
  5.  
    字段 类型
  6.  
    );

注意: 默认值必须与字段类型一致。

8.8、给表中字段添加约束

8.8.1、给表中字段添加主键约束

alter table 表名 add constraint 约束名 primary key(字段名);

8.8.2、给表中字段添加非空约束

alter table 表名 modify 字段名 类型 not null;

8.8.3、给表中字段添加唯一约束

alter table 表名 add constraint 约束名 unique(字段名);

8.8.4、给表中字段添加外键约束

alter table 表名 add constraint 约束名 foreign key(字段名) references 主表名(字段名);

8.8.5、删除表中的约束

删除表中的主键约束

alter table 表名 drop primary key;

删除表中的唯一约束

alter table 表名 drop index 约束名;

删除非空约束

alter table 表名 modify 字段名 类型 null;

删除外键约束

alter table 表名 drop foreign key 约束名;

查询字段约束的详细信息

select *  from  information_schema.table_constraints where table_name='表名';

9、数据操作DML

9.1、添加数据(insert into)

全字段,单行数据添加

insert into 表名 value(值1,值2,...值n);

注意:值的个数、值的顺序、值的类型必须与表中的字段一致,如果某个字段不需要添加值,则以null占位。

部分字段添加数据

insert into 表名(字段名,字段名) value(值1,值2);

注意:值的个数、值的顺序、值的类型 必须与表名后指定的字段一致。

多行数据添加

  1.  
    insert into 表名 values(值1,....值n),
  2.  
    (值1...值n),
  3.  
    ....
  4.  
    (值1...值n);

复制添加

insert into 表名 select 字段,....字段 from 表名;

注意事项:
1、查询的字段个数、字段类型、字段顺序要与表中字段一个一个地对应。
2、不能违反添加数据的表中的约束条件。

9.2、修改数据(update)

对指定字段下的所有值进行修改

update 表名 set 字段名1=值,字段2=值;

修改指定行的信息

update 表名 set 字段名=值 where 条件;

9.3、删除数据(delete)

清空表中数据,可通过 rollback 找回。

delete  from 表名;

截断表,不可通过rollback找回,删除数据的速度特别快。

truncate table 表名;

删除部分数据

delete from 表名  where 条件;

10、数据查询DQL

10.1、单表查询

查询所有字段

select * from 表名;

查询部分字段

select 字段1,.... 字段n from  表名;

去重查询(distinct)

select distinct 字段 from 表名;

排序查询(order by),默认为升序排序

select * from 表名 order by 字段名;

降序排序 desc

select * from 表名 order by 字段名 desc; 

多字段排序

select * from 表名 order by 字段1,字段2...字段n;

注意:
1、多字段排序时,第一个字段中重复的内容再根据第二个字段排序,第二个字段如果依然有重复,再根据后续字段进行排序。
2、多字段排序时如果每个字段都需要进行降序排序,则每个字段后都需要 desc

单条件查询

1、比较运算符进行条件设置

条件判断 说明
= 恒等
!= 非等 
> 大于
< 小于
>= 大于等于
<= 小于等于
where 字段>值 字段大于判断
where 字段<值 字段小于判断

 2、betweent and 范围查询

select * from 表名 where 字段 between 值 and 值;

等同于

select * from 表名 where 字段>=值 and 字段<=值;

3、空值查询和非空值查询

空值查询

select * from 表名 where 字段 is null;

非空查询

select * from 表名 where 字段  is not null;

注意
0、"null"、“NULL” 都不是 null

4、模糊查询 like

配合通配符使用 %或_ ,%:任意长度任意字符。   _: 匹配单个任意字符。

select * from 表名 where 字段 like “关键词%”;

5、包含查询  in  和 not in

字段的值只要符合()中的任意一个值即成立。

in

select * from 表名 where 字段 in (值1,值2,....值n);

等同于

select * from 表名 where 字段 =值1 or 字段=值2 or....字段=值n;

not in

select * from 表名 where 字段 not in (值1,值2,....值n);

等同于

select * from 表名 where 字段 !=值1 and 字段!=值2  and ....字段!=值n;

多条件查询

1、分组查询(group by)

select 分组字段 from 表名 group by 分组字段;

进行分组筛选

select 分组字段 from 表名 group by 分组字段 having 条件;

having 之后的条件只能通过分组字段或聚合函数进行设置,可以在 group by 之前写 where 条件查询,但是含义不同。

2、聚合函数查询

统计数量count(*),求字段中的最大值max(字段名),求字段中的最小值min(字段名),求字段中值的和sum(字段名),求平均值avg (字段名),通常,聚合函数和聚合函数一起使用,或和分组字段一起使用。

3、常用函数查询

1、字符串函数

获取字符串长度
char_length(字段名或字符串)

拼接字符串
concat()用来进行字符串拼接
concat(字符串1,字符串2...,字符串n)

注意:在mysql中 号不能拼接,字符串中如果为整数,那么会自动转换为整数类型。

截取字符串
substring(字符串或字段名,起始位置,截取长度);
起始位置是从1开始。

替换内容
replace(字符串,原有内容,新内容)

字符大写形式
upper(字符串)

字符小写形式
lower(字符串)

把日期字符串解析为日期
str to date ("日期字符串","格式");

2、日期函数

获取系统日期
now()

把日期按照指定格式,转换为字符串
date_format(日期,"格式");

%Y  四位年
%y  两位年
%m 月 2位数
%c   月 
%d  日
%h  时
%i   分
%s  秒


求两个日期的相差天数
datediff(日期1,日期2);


日期加减
adddate(日期,interval 相加数量 类型);
adddate(日期,interval 2 DAY);
注意:减日期就是把天数改为负数

3、数学函数

向上取整
ceiling(数字)

向下取整
floor(数字)

四舍五入取整
round(数字)

求次幂

pow(数字,次方)

平方根

SQRT(数字)

4、别名查询 

1、字段别名

给查询结果中的内容指定一个新的字段名称

select 字段 as 别名,字段 as 别名 from 表名;

as 使用在 where 之前,不能用于 where 之后,可以省略,可以使用在 order by 之后。

2、表别名

多表查询时,替代表名,表名  as  别名,as 可以省略,在 where 之后可以使用。

10.2、多表查询 

10.2.1、连表查询

1、多表查询之无条件多表查询

select * from 表1,表2,表3;

笛卡尔积形式,但是这样查出来的数据没有任何意义。 

2、条件筛选查询

select * from 表1,表2 where 表1.字段=表2.字段;

 有关联表字段进行相连,与字段的数据有关,与字段的名字无关。

3、连接查询join查询

3.1、外连接

左外连接  left join

select * from 表1 left join 表2 on 表1.字段=表2.字段;

注意:
左表中数据会全部展示,右表中只展示与左表关联的数据。左表中未找到连接信息的数据,则右表部分用 null 填充。
右外连接 right join

select * from 表1 right join 表2 on 表1.字段=表2.字段;

全外连接 full join (mysql中不生效,这里不再整理) 

3.2、内连接  inner join

select * from 表1 inner join 表2 on 表1.字段=表2.字段;

注意:内连接只显示符合连接条件的信息,inner可以省略不写。

10.2.2、子查询

一个查询语句中包含其它一个或多个其它查询语句。
例如:查询成绩不及格的学生信息

select * from student where stuid in (select stuid from score where grade < 60)

exists 查询(替代 in 查询)

select * from student where exists ( select * from score where score.stuid = student.stuid and score <60);

not exists 不存在,对exists取反

select * from student where not exists ( select * from score where score.stuid = student.stuid and score <60);

11、用户权限DCL

11.1、创建用户

create user '用户名'@'主机名' identified by '密码';

注意:
主机名:限定客户端登录ip
指定ip:127.0.0.1 (localhost)
任意ip:%

实例

create user 'jack'@'%' IDENTIFIED by 'jack';	

11.2、查看权限

show grants for '用户名'@'主机名';

实例

show grants for 'jack'@'%';

11.3、授予权限

11.3.1、授予单个权限

授于 select 单个权限,jack 这个用户对test库的emp表有select操作权限

grant select on test.emp to 'jack'@'%' ;

授予权限后,刷新权限

flush privileges;

11.3.2、授予多个权限

授于 select, update , insert 多个权限,jack 这个用户对test库的emp表

  1.  
    grant select, update , insert on test.emp to 'jack'@'%' ;
  2.  
    -- 刷新权限
  3.  
    flush privileges;

11.3.3、授予全部、指定的库和表

  1.  
    --授于整个test 库的权限
  2.  
    --jack 这个用户对test库下的所有表有操作权限
  3.  
    grant all on test.* to 'jack'@'%' ;
  4.  
    -- 刷新权限
  5.  
    flush privileges;
  1.  
    -- 授于整个test 库的权限
  2.  
    -- jack 这个用户对所有库下的所有表有操作权限
  3.  
    grant all on *.* to 'jack'@'%' ;
  4.  
    -- 刷新权限
  5.  
    flush privileges;

11.4、撤销授权

revoke 权限1,权限2... on 数据库名.表名 from '用户名'@'主机名'; 

演示 

  1.  
    -- 撤销jack用户下test库中的emp表的select权限
  2.  
    revoke select on test.emp from 'jack'@'%' ;
  3.  
     
  4.  
    -- 撤销jack用户下test库所有表的select权限
  5.  
    revoke select on test.* from 'jack'@'%' ;

11.5、删除用户

drop user '用户名'@'主机名';

演示 

drop user 'jack'@'%' ;

11.6、密码管理

11.6.1、超级管理用户的密码修改

修改mysql服务器中自带的mysql数据库的user表下有一个authentication_string修改即可

update user set authentication_string =password('abc') where user='root';  

或者以下代码 

set password for 'root'@'localhost' = password('abc');

11.6.2、普通用户修改密码

set password=password('新密码');

12、三大范式

12.1、数据库第一范式

数据库表的每一列都是不可分割的基本数据项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性。(保持数据的原子性)

数据原子性很好理解,就是表中的字段不可再分。符合数据库第一范式的表,每个字段表意明确,看个例子:

学新通

这是一张简单的员工信息表,其中有工号、姓名、电话三个字段。通过电话这个字段获得的信息有可能是家庭电话,或是工作地点的电话,或是手机,因此表达的信息并不明确,我们可以改成这样:

学新通

第一范式: 必须明确字段

12.2、数据库第二范式

在满足第一范式的基础上,实体的每个非主键属性完全函数依赖于主键属性(消除部分依赖)

主键:主键明确标识了每条记录,一般是一个字段,也可以由两个或两个字段组成。

依赖:对于X的每个值,Y都有一个值与之对应,反过来则不一定不成立,这叫做X函数决定Y,Y函数依赖X(X往往是主键)。

还拿上面的那张表举来说,对于每个工号,都有一个姓名与之对应,即工号决定姓名,姓名依赖工号;但由于员工之间可能有重名,一个姓名可能对应多个工号,所以姓名不能决定工号。

部分依赖:当主键由两个或两个以上字段构成,而表中的某些信息通过主键的一个字段就能唯一确定,我们称这样的依赖关系为部分依赖,比如这个例子:

学新通

学生选课(学号,姓名,专业,课程号,课程名,成绩),该表中一个学生可以选多门课,一门课有多个学生。学号和课程号可以唯一确定一条记录,因此用学号和课程号做主键。

表中的姓名、专业通过主键中的学号就能唯一确定,而课程名通过课程号唯一确定,这就是部分依赖,这样的设计不符合第二范式。

不符合第二范式会带来哪些问题呢?

1、数据信息冗余,可见上表。

2、增删改会出现问题,比如有一门《微机原理》没有人选,那么由于缺少学号(主键之一)那么这门课就不能出现在表里。

解决方法

学新通

学新通

让每张表只做每张表的事即可,不要把所有事都集中一块

第二范式:在第一范式的基础上,明确每一张表。

12.3、数据库第三范式

在满足第二范式的基础上,在实体中不存在非主键属性传递函数依赖于主键属性。(表中字段[非主键]不存在对主键的传递依赖)

传递依赖:A依赖于B,B依赖于C,就可以说A依赖C。

学新通

在这样一张表中则存在着传递依赖。也就是系名依赖系号,系号依赖学号,那么间接的系名依赖学号,宿舍号、宿舍电话和学号之间也有同样的关系。这样设计表的同样会带来数据冗余,操作异常等问题。那么我们同样可以用关系分解的分解的方法来消除传递依赖,将这张表分成三张表:

学新通

 第三范式: 在第一范式和第二范式的基础上,让表与表之间建立关系。

13、索引

索引有作用: 提高查询的效率。一般用于数据量比较大的情况下我们建立索引,如果数据量太小也必要去建立索引。

  1.  
    -- 创建索引
  2.  
    create index abc on emp(ename);
  3.  
     
  4.  
    -- 查看索引
  5.  
    show index from emp;
  6.  
     
  7.  
    -- 测试索引
  8.  
    select * from emp where ename = "name1577";
  9.  
     
  10.  
    -- 删除索引
  11.  
    drop index abc on emp;

14、横表和纵表的转换

14.1、纵表转横表

首先创建一个表为proper

  1.  
    create table proper(
  2.  
    student_name varchar(20),
  3.  
    course_name varchar(20),
  4.  
    score double
  5.  
    );
  6.  
     
  7.  
    INSERT INTO `proper`(`student_name`, `course_name`, `score`) VALUES ('张三', '语文', 67);
  8.  
    INSERT INTO `proper`(`student_name`, `course_name`, `score`) VALUES ('张三', '数学', 78);
  9.  
    INSERT INTO `proper`(`student_name`, `course_name`, `score`) VALUES ('李四', '语文', 90);
  10.  
    INSERT INTO `proper`(`student_name`, `course_name`, `score`) VALUES ('李四', '英语', 89);

学新通

转表

  1.  
    select
  2.  
    -- 第一列显示的字段
  3.  
    p.student_name,
  4.  
    -- 当course_name的名字是‘语文’,把对应的成绩显示
  5.  
    sum(case p.course_name when '语文' then p.score end ) as 语文,
  6.  
    sum(case p.course_name when '数学' then p.score end ) as 数学,
  7.  
    sum(case p.course_name when '英语' then p.score end ) as 英语
  8.  
    from proper p
  9.  
    -- 对名字进行分组
  10.  
    group by p.student_name

 学新通

14.2、横表转纵表

  1.  
    create table score_horizontal (
  2.  
    student_name varchar(20),
  3.  
    chinese varchar(20),
  4.  
    math varchar(20),
  5.  
    english varchar(20)
  6.  
    );
  7.  
     
  8.  
    INSERT INTO `score_horizontal`(`student_name`, `chinese`, `math`, `english`) VALUES ('张三', '67', '78', NULL);
  9.  
    INSERT INTO `score_horizontal`(`student_name`, `chinese`, `math`, `english`) VALUES ('李四', '90', NULL, '89');

学新通

转表

  1.  
    select s.student_name,'chinese' as 科目,s.chinese as 成绩 from score_horizontal s
  2.  
    union
  3.  
    select s.student_name,'math' as 科目,s.math as 成绩 from score_horizontal s
  4.  
    union
  5.  
    select s.student_name,'english' as 科目,s.english as 成绩 from score_horizontal s;

 学新通

15、悲观锁和乐观锁

乐观锁是在应用层加锁,而悲观锁是在数据库层加锁(for update)。
乐观锁顾名思义就是在操作时很乐观,这数据只有我在用,我先尽管用,最后发现不行时就回滚。
悲观锁在操作时很悲观,生怕数据被其他人更新掉,我就先将其先锁住,让别人用不了,我操作完成后再释放掉。
悲观锁需要数据库级别上的的实现,程序中是做不到的,如果在长事务环境中,数据会一直被锁住,导致并发性能大大地降低。
一般来说如果并发量很高的话,建议使用悲观锁,否则的话就使用乐观锁。
如果并发量很高时使用乐观锁的话,会导致很多的并发事务回滚、操作失败。
总之,冲突几率大用悲观,小就用乐观。

创建表准备工作

  1.  
    CREATE TABLE t_user (
  2.  
    id int(11) NOT NULL AUTO_INCREMENT,
  3.  
    name varchar(255) DEFAULT NULL,
  4.  
    PRIMARY KEY (`id`)
  5.  
    ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
  6.  
     
  7.  
    insert into t_user value('1','jack');
  8.  
    insert into t_user value('2','rose');
  9.  
    insert into t_user value('3','tom');

15.1、行级锁

  1.  
    -- 1、开启事务
  2.  
    start transaction;
  3.  
     
  4.  
    -- 2、开启悲观锁(加锁),这条数据其他人是无法修改的(只针对 update delete 操作加锁)
  5.  
    select * from t_user where id = 1 for update;
  6.  
     
  7.  
    -- 3、新开一个窗口,模拟另一个用户操作
  8.  
    -- 对加锁的数据进行修改,此时是无法修改,因为锁没有释放
  9.  
    update t_user set name = 'tom' where id = 1;
  10.  
     
  11.  
    -- 查看数据是否被修改
  12.  
    select * from t_user;
  13.  
     
  14.  
    -- 4、释放锁(事务提交)别人才能操作
  15.  
    commit;
学新通

15.2、表级锁

  1.  
    -- 1、开启事务
  2.  
    start transaction;
  3.  
     
  4.  
    -- 2、开启悲观锁(加锁),这条数据其他人是无法修改的(只针对 insert update delete 操作加锁)
  5.  
    select * from t_user for update;
  6.  
     
  7.  
    -- 3、打开新窗口模拟另一个用户操作
  8.  
    update t_user set name = 'aa' where id = 3; -- 被加锁
  9.  
    delete from t_user where id = 3; -- 被加锁
  10.  
    insert into t_user values(null,'bb'); -- 被加锁
  11.  
    select * from emp; -- 正常操作
  12.  
     
  13.  
    -- 4、释放锁
  14.  
    commit;

16、MySQL引擎

16.1、Innodb引擎

Innodb引擎提供了对数据库ACID事务的支持,并且实现了SQL标准的四种隔离级别。该引擎还提供了行级锁和外键约束,它的设计目标是处理大容量数据库系统,它本身其实就是基于MySQL后台的完整数据库系统,MySQL运行时Innodb会在内存中建立缓冲池,用于缓冲数据和索引。但是该引擎不支持FULLTEXT类型的索引,而且它没有保存表的行数,当SELECT COUNT(*) FROM TABLE时需要扫描全表。当需要使用数据库事务时,该引擎当然是首选。由于锁的粒度更小,写操作不会锁定全表,所以在并发较高时,使用Innodb引擎会提升效率。但是使用行级锁也不是绝对的,如果在执行一个SQL语句时MySQL不能确定要扫描的范围,InnoDB表同样会锁全表。

16.2、MyIASM引擎

MyIASM是MySQL默认的引擎,但是它没有提供对数据库事务的支持,也不支持行级锁和外键,因此当INSERT(插入)或UPDATE(更新)数据时即写操作需要锁定整个表,效率便会低一些。不过和Innodb不同,MyIASM中存储了表的行数,于是SELECT COUNT(*) FROM TABLE时只需要直接读取已经保存好的值而不需要进行全表扫描。如果表的读操作远远多于写操作且不需要数据库事务的支持,那么MyIASM也是很好的选择。

16.3、Innodb引擎、MyIASM引擎区别

1、MyIASM是非事务安全的,而InnoDB是事务安全的
2、MyIASM锁的粒度是表级的,而InnoDB支持行级锁
3、MyIASM支持全文类型索引,而InnoDB不支持全文索引
4、MyIASM相对简单,效率上要优于InnoDB,小型应用可以考虑使用MyIASM
5、MyIASM表保存成文件形式,跨平台使用更加方便

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhfjiihi
系列文章
更多 icon
同类精品
更多 icon
继续加载