MySQL从建库到删库跑路 -- 5.数据类型

5 数据类型

5.1 数值类型

python 复制代码
create table num_types 
(
	bit_ bit, # 比特,最小数值类型,位类型
	tinyint_ tinyint, # [-128, 127]
	bool_ bool, # 0 and 1
	smallint_ smallint, # [-2^15, 2^15 - 1]
	int_ int, # [-2^31, 2^31 - 1]
	bigint_ bigint, # [-2^63, 2^63 - 1]
	float_ float, # 大小在4字节,你可以在后面接(M, D)自定义显示长度(M)和小数点后的位数(D)
	double_ double, # 大小在8字节,同样可以使用(M, D)
	decimal_ decimal # 一个特殊的浮点数类型,可以指定任意长度,换句话说,(M, D)可以几乎完全自定义,几乎没有限制,这在精度刚需的数据中很有用,我这里没有指定,所以实际不会显示小数
);
sql 复制代码
mysql> create table num_types 
	-> (
	->   bit_ bit, 
	->   tinyint_ tinyint, 
	->   bool_ bool, 
	->   smallint_ smallint, 
	->   int_ int, 
	->   bigint_ bigint, 
	->   float_ float, 
	->   double_ double, 
	->   decimal_ decimal
	-> );
Query OK, 0 rows affected (0.02 sec)

mysql> show create table num_types\G
*************************** 1. row ***************************
       Table: num_types
Create Table: CREATE TABLE `num_types` (
  `bit_` bit(1) DEFAULT NULL,
  `tinyint_` tinyint DEFAULT NULL,
  `bool_` tinyint(1) DEFAULT NULL,
  `smallint_` smallint DEFAULT NULL,
  `int_` int DEFAULT NULL,
  `bigint_` bigint DEFAULT NULL,
  `float_` float DEFAULT NULL,
  `double_` double DEFAULT NULL,
  `decimal_` decimal(10,0) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)

mysql> insert into num_types (bit_, tinyint_, bool_, smallint_, int_, bigint_, float_, double_, decimal_) 
    -> values(
    ->   b'1',
    ->   127,
    ->   true,
    ->   32767,
    ->   -2147483648,
    ->   9223372036854775807,
    ->   1.23456789,
    ->   1.23456789012345,
    ->   999999.99
    -> );
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> select * from num_types\G
*************************** 1. row ***************************
     bit_: 0x01
 tinyint_: 127
    bool_: 1
smallint_: 32767
     int_: -2147483648
  bigint_: 9223372036854775807
   float_: 1.23457
  double_: 1.23456789012345
 decimal_: 1000000
1 row in set (0.00 sec)
  • 注意:

    1. float和double的自定义(M, D)功能其实已经在MySQL 8.0.17版本被弃用了,即便你用了也只会造成显示层面的改变,实际不会改变其存储的数值
    2. decimal的(M, D)存在物理上限,M最大为65,D最大为30,且不能超过M
    3. 可以用UNSIGNED来让其变成一个无符号的数
    4. bit支持以bit(M)的形式指定长度,除非大小直接超过了65535字节
    5. 虽然几乎所有整形都支持类似于bit(M)的语法,但是实际意义不一样,比方说int(5)在另一个关键字zerofill的加持下表示尽量显示五位数字(如果没有这个关键字,那就没有任何意义),对标浮点数的(M, D)
  • 测试一下(M, D)与UNSIGNED,以及上一小节说过的临时表

  • 这里你能看到,临时表是可以同名的,不过缺点是,如果你想现在用同名的非临时表,就只能先想办法删除/销毁这个临时表,才可以用非临时表,因为同名了,所以默认情况下会始终使用临时表
  • 退出之后重进会导致临时表被销毁,此时查表就只能查到非临时表了

5.2 字符串类型

sql 复制代码
create table char_types (
	-- char如果没有指定数值,那么默认就是1个字符的大小
	char_ char,   
	-- char的最大值,也就是最多连续255个字符
	char_max_ char(255),    
	-- varchar必须指定长度
	-- 实际上这不是varchar的最大值,而是估算的最大值,后续会提到
	varchar_max_ varchar(16000)  

	-- 注意,这里我们说的是字符数!如果换算成字节,需要根据编码来实际判断
);
  • 如果你尝试把varchar指定一个比较大的数值,多半会报错,我们打个比方
  • 假设现在字符集是utf8mb4,那么一个字符要吃掉大约4字节,我们在"数值类型"说过,指定长度不能超过65535字节,那么也就是说,varchar在这种情况下最多也就存大约16,383个
    字符,同时,varchar其实还会多用一些空间,有一些隐藏开销,比方说实际上varchar_max_也会占用空间,所以我这里也就填了16000
类型 本质 长度上限 性能 应用场景
char 定长数组 255个字符,一般不会顶到65535字节的上限 性能很不错,但是缺点是一旦开辟就一定会占用对应大小的空间 卡号,ID号等等长度固定的数据储存
varchar 变长数组 长度上线取决于使用的字符集 性能会比char差一些,因为可能要做分页或者移动什么的,但是非常能节约空间 长度不固定的数据存储,像是用户的评论什么的
  • 值得一提的是,char在没有存储有效数据的部分(一般是尾部),其实是全部填充空格的

5.3 枚举和选项

sql 复制代码
create table test_enum_and_set(
  name varchar(64),
  -- 枚举类型
  -- 和C语言的枚举类型类似,定义的时候创建索引,实际存储数字
  -- 搜索的时候会找索引中对应的值
  -- 使用的时候也可以直接输入数字
  gender enum('xiaonanniang', 'cixiaogui', 'guzhangjiqiren'),
  -- 集合类型
  -- 实际上是一个位图,定义的时候会创建索引
  -- 区别于enum,set类型允许存在若干个选项/值,所以用位图更加省空间
  cards set('daji', 'fangyu')
);
  • 插几个值
sql 复制代码
mysql> insert into test_enum_and_set values('chujun', 'cixiaogui', 'daji,fangyu');
Query OK, 1 row affected (0.01 sec)

mysql> insert into test_enum_and_set values('xiaolanren', 'guzhangjiqiren', 1);
Query OK, 1 row affected (0.01 sec)

mysql> insert into test_enum_and_set values('ni', 1, 2);
Query OK, 1 row affected (0.01 sec)
  • 搜一下
markdown 复制代码
mysql> select * from test_enum_and_set\G
*************************** 1. row ***************************
  name: chujun
gender: cixiaogui
 cards: daji,fangyu
*************************** 2. row ***************************
  name: xiaolanren
gender: guzhangjiqiren
 cards: daji
*************************** 3. row ***************************
  name: ni
gender: xiaonanniang
 cards: fangyu
3 rows in set (0.00 sec)
  • 可以指定字段查询
markdown 复制代码
mysql> select * from test_enum_and_set where gender = 'xiaonanniang'\G
*************************** 1. row ***************************
  name: ni
gender: xiaonanniang
 cards: fangyu
1 row in set (0.00 sec)
  • 你会发现这里其实匹配有点严格,因为只查出来只有fangyu的行
  • 所以我们可以用个函数,find_in_set(str, strlist),如果str在strlist中,就会返回1,否则返回0
  • 放在这个语境,就是挑出符合"'daji'在cards"中的行
markdown 复制代码
mysql> select * from test_enum_and_set where find_in_set('daji', cards)\G
*************************** 1. row ***************************
  name: chujun
gender: cixiaogui
 cards: daji,fangyu
*************************** 2. row ***************************
  name: xiaolanren
gender: guzhangjiqiren
 cards: daji
2 rows in set (0.00 sec)
相关推荐
Lysander.Jovian6 分钟前
mysql数据库基本使用
mysql
Shadow(⊙o⊙)35 分钟前
MySQL索引
数据库·mysql
fb_123451 小时前
MySQL运维实战:备份恢复+主从复制+读写分离+MHA高可用(超详细手把手教程)
运维·mysql·oracle
杨云龙UP2 小时前
一次数据库查询缓慢故障复盘:大表数据增长、SQL全表扫描导致系统响应异常
linux·运维·服务器·数据库·sql·mysql
stark张宇3 小时前
从页、区、段到 B+Tree:InnoDB 表空间如何组织数据?
mysql
JAVA面经实录9175 小时前
Java高级后端 · 全套面试通关手册(MySQL)
java·mysql·面试
java1234_小锋5 小时前
【技术专题】Mysql8 数据库 - Mysql8 简介 & 安装以及配置
数据库·mysql
斯内普吖6 小时前
(开源)水果蔬菜商城实战指南 基于 Java + SSM + Vue + MySQL
java·vue.js·mysql·开源
做运维的阿瑞6 小时前
mysql数据库分组查询:GROUP BY 与 HAVING 的执行逻辑
数据库·sql·mysql
沐欣工作室_lvyiyi7 小时前
基于物联网的智能商业零售管理系统设计与实现(论文+源码)
物联网·mysql·mysql数据库·零售