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. floatdouble的自定义(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),如果strstrlist中,就会返回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)
相关推荐
黄俊懿2 小时前
复合索引设计指南:最左前缀 & 字段排座次
数据库·sql·mysql·adb·性能优化·dba·db
Fan_-_2 小时前
MySQL / PostgreSQL DDL 审核自动化:从人工 review 到 CI 拦截
mysql·postgresql·自动化
思麟呀3 小时前
MySQL表的约束
数据库·mysql
罗超驿3 小时前
9.深度剖析MySQL约束的工程设计:自增主键的分布式局限、外键约束的权衡,与CHECK的版本适配实践
数据库·mysql
jiayong233 小时前
MySQL 8.0 数据库恢复问题完整解决方案
数据库·mysql
@小柯555m4 小时前
MySql(正则表达式--电话号码格式校验)
数据库·sql·mysql·正则表达式
重生之小比特4 小时前
【MySQL 数据库】复合查询
android·数据库·mysql
YL200404264 小时前
MySQL-基础篇-约束
数据库·mysql
Mahir085 小时前
MySQL 事务全解:从 ACID 特性到并发问题,再到底层实现与线上最佳实践
数据库·mysql·面试