MySQL基础
- 1. 数据类型
- 1.1 整数类型
- 1.2 浮点类型
- 1.3 定点数类型
- 1.4 位类型
- 1.5 日期时间类型
- 1.6 文本字符串类型
- 1.6.1 CHAR类型和VARCHAR类型
- 1.6.2 TEXT类型
- 1.7 ENUM枚举类型
- 1.8 SET类型
- 1.9 二进制字符串类型
- 1.10 JSON数据类型
- 2. 约束
- 2.1 前置知识
- 2.1.1 为什么需要约束
- 2.1.2 约束是什么
- 2.1.3 约束分类
- 2.1.4 查看数据表约束
- 2.2 不同约束
- 2.2.1 非空约束NOT NULL
- 2.2.1.1 添加非空约束
- 2.2.1.1 删除非空约束
- 2.2.2 唯一性约束UNIQUE
- 2.2.2.1 添加唯一性约束
- 2.2.2.2 删除唯一性约束
- 2.2.3 主键约束PRIMARY KEY
- 2.2.3.1 添加主键约束
- 2.2.3.2 删除主键约束
- 2.2.4 自增约束AUTO_INCREMENT
- 2.2.4.1 添加自增约束
- 2.2.4.2 删除自增约束
- 2.2.5 外键约束FOREIGN KEY
- 2.2.5.1 添加外键约束
- 2.2.5.2 删除外键约束
- 2.2.6 检查约束CHECK
- 2.2.7 默认值约束DEFAULT
- 2.2.7.1 添加默认值约束
- 2.2.7.2 删除默认值约束
- 3. 面试题
1. 数据类型
- 定义数据类型时,如果确定是 整数 ,就用 INT ; 如果是 小数 ,一定用定点数类型
DECIMAL(M,D) ; 如果是日期与时间,就用 DATETIME ; - 任何字段如果为非负数,必须是 UNSIGNED;
- 小数类型为 DECIMAL,禁止使用 FLOAT 和 DOUBLE;
说明:在存储的时候,FLOAT 和 DOUBLE 都存在精度损失的问题,很可能在比较值的时候,得
到不正确的结果。如果存储的数据范围超过 DECIMAL 的范围,建议将数据拆成整数和小数并
分开存储。 - 如果存储的字符串长度几乎相等,使用 CHAR 定长字符串类型;
- VARCHAR 是可变长字符串,不预先分配存储空间,长度不要超过 5000。如果存储长度大
于此值,定义字段类型为 TEXT,独立出来一张表,用主键来对应,避免影响其它字段索引效率;
- 关于字符集设置CHARACTER SET 字符集名或CHARSET 字符集名:1)可在配置文件my.ini中指定整个数据库的字符集;2)可在创建数据库时指定当前数据库的字符集;3)可在创建数据表时指定该表的字符集;4)可在创建表,指定字段时设置该字段的字符集;
如果在某操作中未指定字符集,则字符集向上兼容,比如创建表时未指定,则该表字符集与所属数据库中字符集一致; - 对于整数类型分为有符号整数和无符号整数,默认为有符号,可通过UNSIGNED设置为无符号,有符号整数数值区间为:-2n-1~2n-1-1,无符号整数数值区间为:0~2n-1,其中n表示该数值类型所占内存大小的位数,比如INT类型占4字节共32位;注意负数在存储时使用补码表示;
1.1 整数类型
指定整数类型时有三个可选属性:
- 1)UNSIGNED,表示此时为无符号整数类型;
- 2)M,指定可显示宽度,配合ZEROFILL属性使用,从MySQL 8.0.17开始,整数数据类型不推荐使用显示宽度属性;
- 3)ZEROFILL表示使用零填充,会自动指定该字段为无符号类型,即为其添加UNSIGNED属性;配合M属性使用,当字段值不足M位时,使用0对数值进行左填充;
1.2 浮点类型
- FLOAT 和 DOUBLE 这两种数据类型的区别是啥呢?
FLOAT 占用字节数少,取值范围小;DOUBLE 占用字节数多,取值范围也大。 - 为什么浮点数类型的无符号数取值范围,只相当于有符号数取值范围的一半,也就是只相当于有符号数取值范围大于等于零的部分呢?
MySQL 存储浮点数的格式为: 符号(S) 、 尾数(M) 和 阶码(E) 。因此,无论有没有符号,MySQL 的浮点数都会存储表示符号的部分。因此, 所谓的无符号数取值范围,其实就是有符号数取值范围大于等于零的部分。 - 浮点数是不准确的,要避免使用“=”来判断两个数是否相等,精度要求较高时不要使用浮点数;
关于浮点数有两个属性可指定: - UNSIGNED,表示此时为无符号类型,但浮点数此时并不会扩大数值范围;
- FLOAT(M,D) 和DOUBLE(M,D)可指定浮点数精度和标度,整数部分超出范围则会报错,而小数部分超出范围会先进行四舍五入。MySQL 8.0.17开始,FLOAT(M,D) 和DOUBLE(M,D)用法在官方文档中已经明确不推荐使用;
1.3 定点数类型
- 在使用定点数时,可使用DECIMAL(M,D)指定可存储数值的有效范围,其中D指小数位数,M=D+整数位数,其中M∈[0,65],D∈[0,30],如果不指定则默认M=10、D=0,超出有效范围会进行四舍五入操作;
- 最大取值范围与DOUBLE类型一样,占用内存大小相同情况下,浮点数可表达数值范围更大;
- MySQL内部以字符串形式存储定点数;
- 精度要求高使用定点数,数值范围要求高使用浮点数;
1.4 位类型
- 插入数据大小不能超过BIT(M)所能支持的最大范围;
- M表示二进制位数;
- 可使用 BIN() 或 OCT()、HEX() 函数对某字段进行查询;
- 可使用BIT类型字段+0的方式查看该字段值的十进制值;
1.5 日期时间类型
-
日期时间类型数据插入时,使用单引号括起来;
-
YEAR类型表示年份,默认存储格式为YYYY四位形式;
-
DATE类型表示日期,以 YYYY-MM-DD 格式或者 YYYYMMDD 格式表示字符串日期,YYYYMMDD格式会被转化为YYYY-MM-DD格式;
-
TIME类型表示时间,以HH:MM:SS格式或HHMMSS格式来表示;
-
DATETIME类型表示日期时间,以YYYY-MM-DD HH:MM:SS格式或YYYYMMDDHHMMSS格式来表示;
-
TIMESTAMP类型表示带时区的日期时间,以YYYY-MM-DD HH:MM:SS格式或YYYYMMDDHHMMSS格式来表示;
1.6 文本字符串类型
1.6.1 CHAR类型和VARCHAR类型
- 此处指定的M实际是指该字段所能存储的最大字符数量,比如CHAR(5)则表示该字段最多只能存储5个字符(不区分中英文);
- 插入数据时,如果自行在字符串后面添加连续空格,则MySQL会在存储时自动去除连续空格,而将其余数据视为有效数据;
- 二者对比:建议使用VARCHAR
1.6.2 TEXT类型
- TEXT类型在插入数据时,不会抹去字符串后面的连续空格,而将这些空格视为有效数据存储;
1.7 ENUM枚举类型
- 插入数据时,只能在建表时声明的成员中选取一个;
- 可通过索引在声明列表中选取成员;
- 如果对应字段没有声明为NOT NULL时,也可以插入NULL值;
1.8 SET类型
- 插入数据时可选择声明列表中的0个(如果对应字段没有声明为NOT NULL时,可插入NULL值)或多个值;
- 插入数据时MySQL会自动删除重复成员;
1.9 二进制字符串类型
- BINARY、VARBINARY中M表示最大可存储的字节数;
- 虽然可使用BLOB系列类型存储图片等二进制数据,但一般开发中不会真正使用数据库存储图片内容,而是将图片存储在服务器磁盘中,数据库中存储的是图片对应的访问路径;
1.10 JSON数据类型
- 如何提取JSON数据:
2. 约束
2.1 前置知识
2.1.1 为什么需要约束
数据完整性:数据完整性(Data Integrity)是指数据的精确性(Accuracy)和可靠性(Reliability)。它是防止数据库中存在不符合语义规定的数据和防止因错误信息的输入输出造成无效操作或错误信息而提出的。
2.1.2 约束是什么
- 约束是表级的强制规定;
- 可以在创建表时规定约束(通过 CREATE TABLE 语句),或者在表创建之后通过 ALTER TABLE 语句规定约束;
- 可以使用 ALTER TABLE 语句删除约束;
2.1.3 约束分类
- 根据约束列数量不同:单列约束(只约束一列)、多列约束(组合约束多列);
- 根据约束范围不同:列级约束、表级约束;
- 根据约束作用不同:
MySQL不支持check约束,但可以使用check约束,而没有任何效果;
2.1.4 查看数据表约束
- 此处只需要指定想要查看的数据表名即可查询该表中的约束情况;
- information_schema 为内置数据库,table_constraints 为information_schema 下的数据表;
#information_schema 数据库名(系统库)
#table_constraints 表名称(专门存储各个表的约束)
SELECT * FROM information_schema.table_constraints
WHERE table_name = '表名称';
2.2 不同约束
2.2.1 非空约束NOT NULL
- 限制字段值不能为NULL;
- 所有数据类型的值都默认为NULL;
- 非空约束为单列约束,不能进行组合约束,但表中可以在多个列分别进行非空约束;
- 非空约束为列级约束,只能在字段后面声明;
- NULL不等同于空字符串’'或0;
2.2.1.1 添加非空约束
1)方式一:建表时指定约束
CREATE TABLE 表名称(
字段名 数据类型,
字段名 数据类型 NOT NULL,
字段名 数据类型 NOT NULL
);
2)方式二:建表后添加约束
ALTER TABLE 表名称 MODIFY 字段名 数据类型 NOT NULL;
2.2.1.1 删除非空约束
ALTER TABLE 表名称 MODIFY 字段名 数据类型;
2.2.2 唯一性约束UNIQUE
- 限制某个字段/某列的值不能重复;
- 可为表中多个列指定唯一约束;
- 既为单列约束,也可为组合多列约束(需作为表级约束声明);
- 既为列级约束,也可为表级约束
- 允许列值为空(NULL),且可有多个NULL值;
- 创建唯一约束时,若不给唯一约束命名,则1)单列约束默认和列名相同;2)组合约束则默认为组合列表中的第一个字段名;
- MySQL会给唯一约束的列上默认创建一个唯一索引;
2.2.2.1 添加唯一性约束
1)方式一:建表时指定
create table 表名称(
字段名 数据类型,
字段名 数据类型 unique,
字段名 数据类型 unique key,
字段名 数据类型
);
create table 表名称(
字段名 数据类型,
字段名 数据类型,
字段名 数据类型,
[constraint 约束名] unique key(字段名)
);
2)方式二:建表后添加
alter table 表名称 add [constraint 约束名] unique key(字段列表);
或
alter table 表名称 modify 字段名 字段类型 unique;
2.2.2.2 删除唯一性约束
- 添加唯一性约束的列上也会自动创建唯一索引;
- 删除唯一约束只能通过删除唯一索引的方式删除;
- 删除时需要指定唯一索引名,唯一索引名就和唯一约束名一样;
- 可通过show index from 表名称 查看表的索引;
ALTER TABLE 表名
DROP INDEX 唯一索引名;
2.2.3 主键约束PRIMARY KEY
- 唯一标识表中的一条记录;
- 可看做非空约束与唯一性约束的结合,主键约束要求字段值非空且唯一;
- 既为列级约束,也为表级约束;
- 既为单列约束,也为多列组合约束;
- 多列约束时,其中所有字段都不能为NULL;
- 表中最多只能有一个主键约束;
- MySQL中主键名恒为PRIMARY;
- 创建主键约束时,会为对应的列建立主键索引(根据主键索引查询效率更高),如果删除了主键约束则对应主键索引也自动删除了;
2.2.3.1 添加主键约束
1)方式一:建表时指定
create table 表名称(
字段名 数据类型 primary key, #列级模式
字段名 数据类型,
字段名 数据类型
);
create table 表名称(
字段名 数据类型,
字段名 数据类型,
字段名 数据类型,
[constraint 约束名] primary key(字段名) #表级模式
)
2)方式二:建表后添加
ALTER TABLE 表名称 ADD PRIMARY KEY(字段列表);
或
ALTER TABLE 表名称 MODIFY 字段 数据类型 PRIMARY KEY;
2.2.3.2 删除主键约束
- 实际开发中不会删除主键约束;
ALTER TABLE 表名 DROP PRIMARY KEY;
2.2.4 自增约束AUTO_INCREMENT
- 设置某个字段值自增,常配合主键字段使用;
- 表中最多只能有一个自增列;
- 自增列必须为键列,如主键、唯一键;
- 自增列数据类型必须为整数;
- 如果向自增列插入0或NULL,MySQL会在当前自增列最大值基础上进行自增;如果插入具体值,则赋值为该值;
- 单列约束,列级约束;
- MySQL8.0对自增变量(计数器)进行持久化;
2.2.4.1 添加自增约束
1)建表时指定
create table 表名称(
字段名 数据类型 primary key auto_increment,
字段名 数据类型 unique key not null,
字段名 数据类型 unique key,
字段名 数据类型 not null default 默认值,
);
create table 表名称(
字段名 数据类型 default 默认值 ,
字段名 数据类型 unique key auto_increment,
字段名 数据类型 not null default 默认值,,
primary key(字段名)
);
2)建表后指定
ALTER TABLE 表名
MODIFY 字段 数据类型 auto_increment;
2.2.4.2 删除自增约束
alter table 表名称 modify 字段名 数据类型;
2.2.5 外键约束FOREIGN KEY
- 保证表中某个字段的引用完整性;
- 被引用的表称为主表(父表),引用表称为从表(子表);
- 被引用的值必须是唯一的,所以从表的外键列必须引用主表的主键列或唯一约束列;
- 创建数据表时,先创建主表,再创建从表;删除时相反,先删除从表,再删除主表;
- 一个表可以建立多个外键约束;
- 创建外键约束时,如果不自定义约束名,则会自动产生一个外键名;
- 从表的外键列与主表被参照的列名字可以不相同,但是数据类型必须一样,逻辑意义一致;
- 当创建外键约束时,系统默认会在所在的列上建立对应的普通索引。但是索引名是外键的约束
名(根据外键查询效率很高); - 删除外键约束后,必须 手动 删除对应的索引;
- 约束等级:
2.2.5.1 添加外键约束
1)建表时指定
create table 主表名称(
字段1 数据类型 primary key,
字段2 数据类型
);
create table 从表名称(
字段1 数据类型 primary key,
字段2 数据类型,
[CONSTRAINT <外键约束名称>] FOREIGN KEY(从表的某个字段) references 主表名(被参考字段)
);
2)建表后指定
ALTER TABLE 从表名
ADD [CONSTRAINT 约束名] FOREIGN KEY (从表的字段) REFERENCES 主表名(被引用字段)
[on update xx][on delete xx];
2.2.5.2 删除外键约束
(1)第一步先查看约束名和删除外键约束
SELECT * FROM information_schema.table_constraints WHERE table_name = '表名称';#查看某个
表的约束名
ALTER TABLE 从表名 DROP FOREIGN KEY 外键约束名;
(2)第二步查看索引名和删除索引。(注意,只能手动删除)
SHOW INDEX FROM 表名称; #查看某个表的索引名
ALTER TABLE 从表名 DROP INDEX 索引名;
2.2.6 检查约束CHECK
- 检查字段值是否满足指定条件,常用作取值范围的检查;
- 列级约束、单列约束;
- MySQL5.7不支持check约束,MySQL8.0支持;
举例:
create table employee(
eid int primary key,
ename varchar(5),
gender char check ('男' or '女')
);
2.2.7 默认值约束DEFAULT
- 指定字段在未插入数据时的默认值;
- 列级约束、单列约束;
- 一般不在唯一键和主键列上加默认值约束;
2.2.7.1 添加默认值约束
1)建表时指定
create table 表名称(
字段名 数据类型 default 默认值 ,
字段名 数据类型 not null default 默认值,
字段名 数据类型 not null default 默认值,
primary key(字段名),
unique key(字段名)
);
2)建表后指定
alter table 表名称 modify 字段名 数据类型 default 默认值;
2.2.7.2 删除默认值约束
alter table 表名 modify 字段 类型;
3. 面试题
- 面试1、为什么建表时,加 not null default ‘’ 或 default 0
答:不想让表中出现null值。 - 面试2、为什么不想要 null 的值
答:(1)不好比较。null是一种特殊值,比较时只能用专门的is null 和 is not null来比较。碰到运算符,通常返回null。
(2)效率不高。影响提高索引效果。因此,我们往往在建表时 not null default ‘’ 或 default 0 - 面试3、带AUTO_INCREMENT约束的字段值是从1开始的吗?
在MySQL中,默认AUTO_INCREMENT的初始值是1,每新增一条记录,字段值自动加1。设置自增属性(AUTO_INCREMENT)的时候,还可以指定第
一条插入记录的自增字段的值,这样新插入的记录的自增字段值从初始值开始递增,如在表中插入第一条记录,同时指定id值为5,则以后插入的记录的id值就会从6开始往上增加。添加主键约束时,往往需要设置字段自动增加属性。 - 面试4、并不是每个表都可以任意选择存储引擎?
外键约束(FOREIGN KEY)不能跨引擎使用。
MySQL支持多种存储引擎,每一个表都可以指定一个不同的存储引擎,需要注意的是:外键约束是用来保证数据的参照完整性的,如果表之间需要关联外键,却指定了不同的存储引擎,那么这些表之间是不能创建外键约束的。所以说,存储引擎的选择也不完全是随意的。
资料来源:
- 尚硅谷;