威尼斯人线上娱乐

mysql字符串类型数据,实例测验MySQL的enum类型

21 7月 , 2019  

在付出品种时日常会超过一些场地字段,举例订单的景况有
待支付、已支付、已关门、已退款
等,作者原先做的花色都以把那一个情形用数字存在数据库中,然后在 php
代码中用常量来维护一份映射表,比方:

实例测量试验MySQL的enum类型,实例mysqlenum

在开采品种时一般会遇见有个别意况字段,比如订单的图景有
待支付、已支出、已关门、已退款
等,小编在此之前做的品类都以把那几个意况用数字存在数据库中,然后在 php
代码中用常量来保养一份映射表,譬如:

const STATUS_PENDING = 0;
const STATUS_PAID = 1;
const STATUS_CLOSED = 2;
const STATUS_REFUNDED = 3;

只是在骨子里行使进度中窥见并不是那么好用,由于各类原因(追查
bug、一时的总结需要等)大家平时供给登入到 mysql 服务器里手动试行一些 sql
查询,由于好多表都有状态字段,写 sql 时务必比照的 php
代码里的照耀关系来写,一相当大心还应该有望将不一致表的情况数字弄混导致大题材。

于是乎自个儿在新品类中策画使用 mysql 的 enum
类型来囤积各类意况,在行使进程中窥见只要在 Laravel 的 migration
文件中对选取了 enum 类型的表做更换(尽管是改造非 enum
类型的字段)都会报错

[Doctrine\DBAL\DBALException]
Unknown database type enum requested, Doctrine\DBAL\Platforms\MySQL57Platform may not support it.

搜索了一晃,发掘是 doctrine 不援救 mysql 的 enum,该文中列举了 enum 的 3
个毛病:

新添 enum 值的时候须求重城建总公司体表,当数据量大的时候恐怕须求开支数时辰。

enum 值的排序法规是按创设表结构时内定的各类,而非字面值的大大小小。

凭仗 mysql 对 enum
值的校验实际不是不行供给,在暗中认可配置下插入违法值最后会成为空值。

依赖新类型的莫过于意况,不太只怕出现须要对事态字段做排序的须要,就算有大家得以在设计表结构的时候就定好顺序,因而短处2 可以忽略;而短处 3
则足以经过代码规范、插入/更新前校验等方法来躲避;至于短处1,我们供给做一些测验。

测量检验希图#

先是创立四个表:

CREATE TABLE `enum_tests` (
 `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 `status` enum('pending','success','closed') COLLATE utf8mb4_unicode_ci NOT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

然后插入 100W 条数据:

$count = 1000000;
$bulk = 1000;
$data = [];
foreach (['pending', 'success', 'closed'] as $status) {
  $data[$status] = [];
  for ($i = 0; $i < $bulk; $i++) {
    $data[$status][] = ['status' => $status];
  }
}

for ($i = 0; $i < $count; $i += $bulk) {
  $status = array_random(['pending', 'success', 'closed']);
  EnumTest::insert($data[$status]);
}

测量检验进程#

测试1#

在 enum 值列表最终增添四个值 refunded

ALTER TABLE `enum_tests` CHANGE `status` `status` ENUM('pending','success','closed','refunded') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL;

输出:

Query OK, 0 rows affected (0.04 sec)
Records: 0 Duplicates: 0 Warnings: 0

结论:在结尾追加 enum 值时差不离从不资本。

测试 2:#

去除刚刚增加的值 refunded

ALTER TABLE `enum_tests` CHANGE `status` `status` ENUM('pending','success','closed') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL;

输出:

Query OK, 1000000 rows affected (5.93 sec)
Records: 1000000 Duplicates: 0 Warnings: 0

结论:删除八个并未有用过的 enum
值仍需全表扫描,开销较高,但还在可承受范围内。

测试 3:#

将 refunded 插入到值列表中间而非末尾

ALTER TABLE `enum_tests` CHANGE `status` `status` ENUM('pending','success','refunded', 'closed') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL;

输出:

Query OK, 1000000 rows affected (6.00 sec)
Records: 1000000 Duplicates: 0 Warnings: 0

结论:在原 enum 值列表中间新扩充钱亟待全表扫描并更新,费用较高。

测试 4:#

删除值列表中间的值

ALTER TABLE `enum_tests` CHANGE `status` `status` ENUM('pending','success','closed') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL;

输出:

Query OK, 1000000 rows affected (4.23 sec)
Records: 1000000 Duplicates: 0 Warnings: 0

结论:需全表扫描,开支较高。

测试 5:#

给 status 字段增加索引后再实践上述测量检验

ALTER TABLE `enum_tests` ADD INDEX(`status`);

发觉测验 2-4 的耗费时间反而有所增添,应该是还要要求立异索引导致的。

结语:#

对于笔者的新品类来讲只看会合世新增加 enum
值的境况,固然未来有各自情形遗弃不用也没有必要去调动 enum
的值列表,因而调整在等级次序中引入 enum 类型作为存款和储蓄状态的数据类型。

在付出项目时一般会越过有的场地字段,比方订单的图景有
待支付、已支付、已关闭、已退款 等,作者…

**字符串类型是在数据库中存款和储蓄字符串的数据类型,字符串类型包涵char,varchar,text,enum和set。

mysql中的explain命令可以用来查阅sql语句是或不是利用了目录,用了怎么着索引,有未有做全表扫描。能够援助咱们优化查询语句。explain出来的音讯有10列,文章重要介绍type、key、Extra那多少个字段。演示中关系到的表结构如下:

const STATUS_PENDING = 0;
const STATUS_PAID = 1;
const STATUS_CLOSED = 2;
const STATUS_REFUNDED = 3;

**

 CREATE TABLE `dept_desc` ( `dept_no` char NOT NULL, `dept_name` varchar NOT NULL, `desc` varchar NOT NULL, PRIMARY KEY (`dept_no`)) ENGINE=InnoDBCREATE TABLE `dept_emp` ( `emp_no` int NOT NULL, `dept_no` char NOT NULL, `from_date` date NOT NULL, `to_date` date NOT NULL, PRIMARY KEY (`emp_no`,`dept_no`), KEY `dept_no` (`dept_no`), CONSTRAINT `dept_emp_ibfk_1` FOREIGN KEY  REFERENCES `employees`  ON DELETE CASCADE, CONSTRAINT `dept_emp_ibfk_2` FOREIGN KEY (`dept_no`) REFERENCES `departments` (`dept_no`) ON DELETE CASCADE) ENGINE=InnoDBCREATE TABLE `employees` ( `emp_no` int NOT NULL, `birth_date` date NOT NULL, `first_name` varchar NOT NULL, `last_name` varchar NOT NULL, `gender` enum NOT NULL, `hire_date` date NOT NULL, PRIMARY KEY ) ENGINE=InnoDB

不过在实质上选择进程中发掘并非那么好用,由于各个缘由(追查
bug、临时的计算供给等)大家常常必要报到到 mysql 服务器里手动实施一些 sql
查询,由于广大表都有事态字段,写 sql 时必须比照的 php
代码里的映照关系来写,一十分大心还会有十分大可能率将区别表的情状数字弄混导致大标题。

OK,大家来一个多个的看下上边提到的两种档案的次序。

上边的表都以mysql中测量检验库的表,需求的同班能够活动去下载。官方文书档案:

于是乎笔者在新品类中计划使用 mysql 的 enum
类型来囤积各个意况,在应用进程中窥见只要在 Laravel 的 migration
文件中对使用了 enum 类型的表做更动(纵然是改换非 enum
类型的字段)都会报错

  • char类型和varchar类型

key

sql语句其实推行时选用的索引列,一时候mysql只怕会挑选优化职能不是最佳的目录,那时,大家得以在select语句中采取force
index(INDEXNAME)来强制mysql使用钦赐索引或使用ignore
index(INDEXNAME)强制mysql忽略钦定索引

[Doctrine\DBAL\DBALException]
Unknown database type enum requested, Doctrine\DBAL\Platforms\MySQL57Platform may not support it.

char类型和varchar类型都以在开创表时钦赐了最大尺寸,其主干格局如下:字符串类型(M)。其中,字符串类型参数钦点了数据类型是char类型照旧varchar类型,M参数钦点了该字符串的最大尺寸为M。举例,char(4)正是指数据类型是char类型,其最大尺寸为4。

type

做客类型,表示数据库引擎查找表的办法,常见的type类型有:all,index,range,ref,eq_ref,const。

  • mysql字符串类型数据,实例测验MySQL的enum类型。all全表扫描,表示sql语句会把表中享有表数据全部读取读取扫描二次。效用最低,我们应尽量防止。

mysql> explain select * from dept_emp;+----+-------------+----------+------+---------------+------+---------+------+--------+-------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+----------+------+---------------+------+---------+------+--------+-------+| 1 | SIMPLE | dept_emp | ALL | NULL | NULL | NULL | NULL | 331570 | NULL |+----+-------------+----------+------+---------------+------+---------+------+--------+-------+
  • index全索引围观,表示sql语句将会把整颗二级索引树全部读取扫描一回,因为二级索引树的数据量比全表数据量小,所以成效比all高级中学一年级些。一般查询语句中询问字段为索引字段,且无where子句时,type会为index。如下,mysql确定使用dept_no这几个目录,然后扫描整个dept_no索引树获得结果。

mysql> explain select dept_no from dept_emp;+----+-------------+----------+-------+---------------+---------+---------+------+--------+-------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+----------+-------+---------------+---------+---------+------+--------+-------------+| 1 | SIMPLE | dept_emp | index | NULL | dept_no | 4 | NULL | 331570 | Using index |+----+-------------+----------+-------+---------------+---------+---------+------+--------+-------------+
  • range部分索引围观,当查问为距离查询,且查询字段为索引字段时,那时会依靠where条件对索引举行局地围观。

mysql> explain select * from dept_emp where emp_no > '7';+----+-------------+----------+-------+---------------+---------+---------+------+--------+-------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+----------+-------+---------------+---------+---------+------+--------+-------------+| 1 | SIMPLE | dept_emp | range | PRIMARY | PRIMARY | 4 | NULL | 165785 | Using where |+----+-------------+----------+-------+---------------+---------+---------+------+--------+-------------+
  • ref现身于where操作符为‘=’,且where字段为非独一索引的单表查询或联表查询。

// 单表mysql> explain select * from dept_emp where dept_no = 'd005';+----+-------------+----------+------+---------------+---------+---------+-------+--------+-----------------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+----------+------+---------------+---------+---------+-------+--------+-----------------------+| 1 | SIMPLE | dept_emp | ref | dept_no | dept_no | 4 | const | 145708 | Using index condition |+----+-------------+----------+------+---------------+---------+---------+-------+--------+-----------------------+// 联表mysql> explain select * from dept_emp,departments where dept_emp.dept_no = departments.dept_no;+----+-------------+-------------+-------+---------------+-----------+---------+-------------------------------+------+-------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+-------------+-------+---------------+-----------+---------+-------------------------------+------+-------------+| 1 | SIMPLE | departments | index | PRIMARY | dept_name | 42 | NULL | 9 | Using index || 1 | SIMPLE | dept_emp | ref | dept_no | dept_no | 4 | employees.departments.dept_no | 1 | NULL |+----+-------------+-------------+-------+---------------+-----------+---------+-------------------------------+------+-------------+
  • eq_ref出现于where操作符为‘=’,且where字段为独一索引联表查询

mysql> explain select * from departments,dept_desc where departments.dept_name=dept_desc.dept_name;+----+-------------+-------------+--------+---------------+-----------+---------+-------------------------------+------+-------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+-------------+--------+---------------+-----------+---------+-------------------------------+------+-------------+| 1 | SIMPLE | dept_desc | ALL | NULL | NULL | NULL | NULL | 1 | NULL || 1 | SIMPLE | departments | eq_ref | dept_name | dept_name | 42 | employees.dept_desc.dept_name | 1 | Using index |+----+-------------+-------------+--------+---------------+-----------+---------+-------------------------------+------+-------------+
  • const出现于where操作符为‘=’,且where字段为独一索引单表查询,此时最多只会协作到一行。

mysql> explain select * from departments where dept_no = 'd005';+----+-------------+-------------+-------+---------------+---------+---------+-------+------+-------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+-------------+-------+---------------+---------+---------+-------+------+-------+| 1 | SIMPLE | departments | const | PRIMARY | PRIMARY | 4 | const | 1 | NULL |+----+-------------+-------------+-------+---------------+---------+---------+-------+------+-------+

综上,单从type字段考虑功效,const > eq_ref > ref > range >
index > all.

留心:大家不能够仅仅依赖type去剖断两条sql的施行进程。譬喻type为range的询问不料定比type为index的全表查询速度要快,还要看现实的sql。因为type为index时,查询是无需回表操作的,而type为range时,有非常大可能率需求回表操作。如sqlA(“select
dept_no from dept_emp;”)和sqlB(“select from_date from dept_emp
where dept_no >
‘d005’;”),那个时候sqlB遵照where条件扫描索引树后,供给回表查询相应的行数据,以获得from_date的值,而sqlA就算扫描了整颗索引树,但并无需回表,所以速度恐怕会比sqlB更加快。

回表操作、索引相关能够阅读<mysql索引初识>那篇文章

寻觅了一下,开掘是 doctrine 不支持 mysql 的 enum,该文中历数了 enum 的 3
个毛病:

char类型的长度是平素的,在开创表时就钦赐了,其尺寸能够是0~~255的任意值。

Extra

extra列会饱含部分那多少个主要的新闻,大家能够依据那些音信实行sql优化

using index:
sql语句未有where查询条件,使用覆盖索引,不须求回表查询就可以得到结果using
where: 未有选取索引/使用了索引但需求回表查询且未有应用到下推索引using
index && useing where:
sql语句有where查询条件,且使用覆盖索引,无需回表查询就能够获得结果。Using
index
condition:使用索引查询,sql语句的where子句询问条件字段均为一样索引字段,且开启索引下推作用,须要回表查询就能够获得结果。Using
index condition && using
where:使用索引查询,sql语句的where子句询问条件字段存在非同一索引字段,且开启索引下推成效,须求回表查询就可以获得结果。using
filesort: 当语句中设有order
by时,且orderby字段不是索引,那个时候mysql不能够运用索引举办排序,只好用排序算法重新开始展览排序,会额外消耗财富。Using
temporary:建构了临时表来保存中间结果,查询实现之后又要把有时表删除。会很影响属性,需尽早优化。

下推索引、覆盖索引相关介绍可观看<mysql索引篇之覆盖索引、前缀索引、索引下推>那篇文章

神跡在extra字段中会现身”Impossible WHERE noticed after reading const
tables”这种描述。翻看网络资料后,个人开采那是mysql一种很怪的管理方式。当sql语句知足:1、依照主键查询大概独一性索引查询;2、where操作符为”=”时。在sql语句优化阶段,mysql会先依据查询条件找到有关记录,那样,假诺那条数据官样文章,实际上就展开了二回全扫描,然后得出一个结论,该数量不在表中。那样对于现身较高的数据库,会加大负载。所以,假设数额并不是独一的话,普通的目录比独一索引越来越好用。(作品链接:

增加产量 enum 值的时候供给重城建总公司体表,当数据量大的时候恐怕必要费用数钟头。

比如,char(100)正是钦命char类型的长短为100。

enum 值的排序准绳是按创立表结构时内定的顺序,而非字面值的深浅。

varchar类型的长度是可变的,在创建表时内定了最大尺寸。定义时,其最大值可以取0~~65525之间的任性值。钦赐了varchar类型的最大值今后,其尺寸能够在o到最大尺寸之间。

依赖 mysql 对 enum
值的校验并非这一个须要,在暗中认可配置下插入违规值最后会化为空值。

举例,varchar(100)的最大尺寸是100,不过,不是每条记下都要占领玖十几个字节。而是在那一个最大值范围内,使用多少分配多少,varchar类型实际占领的上空为字符串的莫过于尺寸加一。那样,就可以有效节约系统的长空。

依照新品类的其实际情状况,不太可能现身供给对景况字段做排序的须求,固然有大家能够在设计表结构的时候就定好顺序,因而缺点2 能够忽略;而劣点 3
则可以通过代码标准、插入/更新前校验等格局来规避;至于缺点1,大家须求做一些测量检验。

如今大家在此处举一个例证,大家向char(5)和varchar(5)中存入区别长度的字符串。以往大家将数据库中的存款和储蓄情势和占用的字节数进行对照,如下图。

测量检验筹划#

威尼斯人线上娱乐 1

先是创立一个表:

关于上海图书馆的演说:

1,不管我们插入的字符串是怎么着子,char(5)所占用的空中都以5个字节。我们前面也说过了,char类型的尺寸固定

2,varchar(5)所占的字节数是实际尺寸的底子上加1。因为字符串的停止标记符占用了二个字节呢。比如说上表中的第四行,varchar将字符串‘123
’最后边的空格还是保存着。

为了确认下空格是还是不是保留,我们后天将数据背后模拟加上‘*’字符,然后来实操下数据库中的char类型和varchar类型。建表语句如下:

[sql] view
plain copy

 

 威尼斯人线上娱乐 2威尼斯人线上娱乐 3

  1. CREATE TABLE `linkinframe`.`test` (  
  2.   `id` INT NOT NULL,  
  3.   `a` CHAR(5) NULL,  
  4.   `b` VARCHAR(5) NULL,  
  5.   PRIMARY KEY (`id`));  

现行反革命我们往数据库中插入几条数据:

[sql] view
plain copy

 

 威尼斯人线上娱乐 4威尼斯人线上娱乐 5

  1. INSERT INTO `linkinframe`.`test` (`id`, `a`, `b`) VALUES (‘1’,”,”);  
  2. INSERT INTO `linkinframe`.`test` (`id`, `a`, `b`) VALUES (‘2′,’1′,’1’);  
  3. INSERT INTO `linkinframe`.`test` (`id`, `a`, `b`) VALUES (‘3′,’123′,’123’);  
  4. INSERT INTO `linkinframe`.`test` (`id`, `a`, `b`) VALUES (‘4’,’123 ‘,’123 ‘);  
  5. INSERT INTO `linkinframe`.`test` (`id`, `a`, `b`) VALUES (‘5′,’12345′,’12345’);  
  6. INSERT INTO `linkinframe`.`test` (`id`, `a`, `b`) VALUES (‘6′,’1234567′,’1234567’);  

宪章数据库数据展现如下:
威尼斯人线上娱乐 6

小结:上面包车型大巴实施证明了二个定论,varchar类型将‘123
’最前边的空格保留着,而char类型中‘123 ’前面包车型的士空格自动删除啦。

CREATE TABLE `enum_tests` (
 `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 `status` enum('pending','success','closed') COLLATE utf8mb4_unicode_ci NOT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

char类型和varchar类型是我们最棒常用的2种字符串类型,关于那2种类型有如下2点特殊表明:

1,假如插入的字符串的长度已经超先生出了足以插入的最大值,那么这年数据库会报错,说data
too long for column。
举个例子,以往大家定义2个char类型和varchar类型的字段,长度都为5,可是我们插入的值是‘123456’,那么系统就能够阻拦这一个值的插入然后报错。
至于插入的字符串长度当先数据定义的长度那么些标题,资料上是地点这么说的,然后平常编码中选拔ORM的时候也远近著名的相逢过这一个荒唐。
但是笔者骨子里sql施行中,比方上边的插入数据库中的最终一条数据,数据库做了截取操作,并从未报错,而是一个警示,调控台出口如下:

Data truncated for column ‘a’ at row 1。 Data truncated for column ‘b’
at row 1

2,大家定义长度的时候定义的数码长度,定义的长度便是字符串最大的尺寸,举个例证,小编定义二个name字段,varchar(6),那么该字段最多可以包容6个汉字。
那一点别和Oracle的varchar2类型的字段搞混淆了。Oracle中的字符串类型2个字节表示三个汉字。
比如,照旧地点的建表语句,今后往里面插入一条字符串的数目,四个超出了字符串定义的长短5,一个平昔不当先,结果超越的字符串被截断啦。

[sql] view
plain copy

 

 威尼斯人线上娱乐 7威尼斯人线上娱乐 8

  1. INSERT INTO `linkinframe`.`test` (`id`, `a`, `b`) VALUES (‘6′,’小编爱您’,’笔者爱您自个儿爱你’);  

数据库现在来得如下:

威尼斯人线上娱乐 9

**

**

  • text类型

text类型是一种奇特的字符串类型。text只好保留字符数据,如新闻的源委等。

text类型满含tinytext,text,mediumtext,longtext。未来将从4种text类型允许的尺寸和仓库储存空间拓展对照,如下图:

威尼斯人线上娱乐 10

下一场插入 100W 条数据:

text类型计算:

这种字符串类型实际中采用并非太多,一般用来直接存储三个非常的大的文件,例如说一篇作品,一篇消息。

从上海教室也得以见见,各样text类型的分别在于允许的长短和存款和储蓄空间不一样。因而在那二种text类型中,依据供给采纳技能满足急需又能节约空间的花色就可以。

 

  • enum类型

enum类型又称之为枚举类型,在创立表时,enum类型的取值范围就以列表的款式钦点了。其主旨方式如下:属性名
enum(‘值1′,’值2′,…,’值n’),在那之中属性名参数钦定字段的称呼,‘值n’参数表示列表中的第n个值,这一个值末尾的空格将会被系统间接删除。注意:

 

1,enum类型的值只好去列表中的贰个成分,其取值列表中最五只可以有655三十个值。列表中的各类值都有贰个顺序排列的编号,MySQL中存入的是其一号码,并不是列表中的值。
2,借使enum类型加上了not
null属性,其暗中同意值为取值列表中的第一个因素。若是不加not
null属性,enum类型将允许插入null,并且null为默许值。

OK,以往我们来实在模拟下MySQL中这种数据类型。

建表语句如下:

[sql] view
plain copy

 

 威尼斯人线上娱乐 11威尼斯人线上娱乐 12

  1. CREATE TABLE `linkinframe`.`test` (  
  2.   `id` INT NOT NULL,  
  3.   `a` ENUM(‘man’, ‘woman’) NULL,  
  4.   PRIMARY KEY (`id`));  

后天大家往数据库中插入几条数据:

[sql] view
plain copy

 

 威尼斯人线上娱乐 13威尼斯人线上娱乐 14

  1. INSERT INTO `linkinframe`.`test` (`id`, `a`) VALUES (‘1’, ‘man’);  
  2. INSERT INTO `linkinframe`.`test` (`id`, `a`) VALUES (‘2’, ‘woman’);  
  3. INSERT INTO `linkinframe`.`test` (`id`, `a`) VALUES (‘3’, null);  
  4. INSERT INTO `linkinframe`.`test` (`id`, `a`) VALUES (‘4’, ‘2’);  
  5. INSERT INTO `linkinframe`.`test` (`id`, `a`) VALUES (‘5’, ‘1’);  
  6. INSERT INTO `linkinframe`.`test` (`id`, `a`) VALUES (‘6’, ‘huhu’);  

今昔数据库呈现如下:

 

**威尼斯人线上娱乐 15

**

$count = 1000000;
$bulk = 1000;
$data = [];
foreach (['pending', 'success', 'closed'] as $status) {
  $data[$status] = [];
  for ($i = 0; $i < $bulk; $i++) {
    $data[$status][] = ['status' => $status];
  }
}

for ($i = 0; $i < $count; $i += $bulk) {
  $status = array_random(['pending', 'success', 'closed']);
  EnumTest::insert($data[$status]);
}

OK,关于enum类型的下结论:

 

1,使用enum类型,数据库中实际上存款和储蓄的各样枚举的号子,并不是列表中的值,所以大家也得以直接插入各样枚举的数码。
2,实际的试行中,假诺本身平素不在该not
null的枚举值上面插入值,或然是无论插入多个值,数据仓库储存款和储蓄的都为空。
3,实际存款和储蓄中,若是不得不选择列表中的一个值,就挑选enum类型,假若急需选取列表中多个值的组合,就必要选择set类型。

 

  • set类型

地点也聊到了,倘若急需选取列表中多少个值的结合,就要选取set类型。在创建表时,set类型的取值范围就以列表的款式钦赐了。其核心情势如下:属性名
set(‘值1′,’值2′,….,’值n’)。其中,‘属性名’属性钦命字段的称呼,‘值n’参数表示列表中的第n个值,那一个值末尾的空格将会被系统直接删除。其大旨方式与enum类型同样。注意:

 

1,set类型的值能够去列表中的二个要素可能两个成分的咬合。去几个成分时,分裂因素之间用逗号隔断。set类型的值最八只好有61个要素结合。

2,同enum类型同样,列表中的每一种值都有三个顺序排列的编号,MySQL中其实存款和储蓄的是其一号码,并非列表中的值。

3,插入记录时,set字段中的成分顺序非亲非故首要,存入MySQL数据库后,数据库系统会活动遵照定义时的相继彰显。OK,今后我们来实操下数据库这种数据类型:
建表语句如下:

[sql] view
plain copy

 

 威尼斯人线上娱乐 16威尼斯人线上娱乐 17

  1. CREATE TABLE `linkinframe`.`test` (  
  2.   `id` INT NOT NULL,  
  3.   `a` SET(‘a’, ‘b’, ‘c’, ‘d’) NOT NULL,  
  4.   PRIMARY KEY (`id`));  

插入几条语句:

[sql] view
plain copy

 

 威尼斯人线上娱乐 18威尼斯人线上娱乐 19

  1. INSERT INTO `linkinframe`.`test` (`id`, `a`) VALUES (‘1’, ‘a’);  
  2. INSERT INTO `linkinframe`.`威尼斯人线上娱乐 ,test` (`id`, `a`) VALUES (‘2’, ‘c’);  
  3. INSERT INTO `linkinframe`.`test` (`id`, `a`) VALUES (‘3’, ‘a,b’);  
  4. INSERT INTO `linkinframe`.`test` (`id`, `a`) VALUES (‘4’, ‘a,b,c,d’);  
  5. INSERT INTO `linkinframe`.`test` (`id`, `a`) VALUES (‘5’, ‘a,e’);  

数据库彰显如下:
威尼斯人线上娱乐 20

 

测量检验进度#

关于set类型的总计:

1,set类型和enum类型对于取值在自然限制的离散值很管用。enum类型只可以在取值列表中取三个值,set类型能够在取值列表中去三个值。

2,这三种档案的次序的多少都不是向来将数据存入数据库,而是将其列表中的编号存入数据库。

3,资料中说借使任凭往那2种档期的顺序中插入数据,会报错,但是小编要好的推行中并从未报错,而是插入八个null。

4,对于set的话,倘若插入五个值,当中多少值合法,有些值违规,那么只会将法定的插入进去,违规的不做管理。

 

测试1#

在 enum 值列表最终增多叁个值 refunded

ALTER TABLE `enum_tests` CHANGE `status` `status` ENUM('pending','success','closed','refunded') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL;

输出:

Query OK, 0 rows affected (0.04 sec)
Records: 0 Duplicates: 0 Warnings: 0

结论:在最后追加 enum 值时差不离平昔不资本。

测试 2:#

去除刚刚增多的值 refunded

ALTER TABLE `enum_tests` CHANGE `status` `status` ENUM('pending','success','closed') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL;

输出:

Query OK, 1000000 rows affected (5.93 sec)
Records: 1000000 Duplicates: 0 Warnings: 0

结论:删除二个不曾用过的 enum
值仍需全表扫描,花费较高,但还在可接受范围内。

测试 3:#

将 refunded 插入到值列表中间而非末尾

ALTER TABLE `enum_tests` CHANGE `status` `status` ENUM('pending','success','refunded', 'closed') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL;

输出:

Query OK, 1000000 rows affected (6.00 sec)
Records: 1000000 Duplicates: 0 Warnings: 0

敲定:在原 enum 值列表中间新扩展值亟待全表扫描并更新,费用较高。

测试 4:#

删除值列表中间的值

ALTER TABLE `enum_tests` CHANGE `status` `status` ENUM('pending','success','closed') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL;

输出:

Query OK, 1000000 rows affected (4.23 sec)
Records: 1000000 Duplicates: 0 Warnings: 0

结论:需全表扫描,费用较高。

测试 5:#

给 status 字段加多索引后再实施上述测验

ALTER TABLE `enum_tests` ADD INDEX(`status`);

发掘测量试验 2-4 的耗费时间相反有所加多,应该是还要必要更新索辅导致的。

结语:#

对于小编的新品类来讲只见面世新扩充 enum
值的境况,即便未来有各自意况放弃不用也无需去调动 enum
的值列表,因而调节在档期的顺序中引进 enum 类型作为存储状态的数据类型。


相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图