重学MySQL系列(三):MySQL数据类型详解

原创做者,公众号【程序员读书】,欢迎关注公众号,转载文章请注明出处哦。mysql

在这篇文章中,咱们来学习MySQL的数据类型,数据类型是MySQL学习中比较基础的知识,但同时也是比较容易被忽略的知识,所以有必要认真学习一下。程序员

固然,不少对数据库有了解的小伙伴应该都知道,MySQL的数据类型,是在建立数据表(Table)的时候,用于指数据表中字段(Field)的类型,即规定字段用存储什么样的数据。sql

好比下面咱们在建立数据表时,在每一个字段名称后面指定了数据表的数据类型。数据库

CREATE TABLE users(
    id INT NOT NULL AUTO_INCREMENT, 
    username VARCHAR(32) NOT NULL,
    email VARCHAR(50) NOT NULL,
    phone CHAR(11) NOT NULL,
);
复制代码

如何查看数据类型

对于已经建立好的数据表,咱们可使用SHOW CREATE TABLE语句查看具体数据表的原始建表SQL语句,好比咱们想知道上面的users数据表的建表语句,能够这样:json

SHOW CREATE TABLE users;
复制代码

执行了上面的语句后,就会打印上面咱们建立数据表的原始SQL语句。数组

MySQL的数据类型

目前MySQL支持的数据类型有:数字类型字符串类型(包括字符)、时间与日期类型空间类型JSON类型,不一样数据类型有不一样的特性,咱们可从该类型的存储空间、取值范围、默认值、如何进行比较,是否能够索引等等方面对其进行学习。bash

注:空间数据类型在平时使用并不太经常使用,所以在咱们的文章中便不做介绍了。函数

数字数据类型

MySQL的数字类型可分为整数类型定点型类型浮点数类型位类型四种类型,下面表格是这四种数据类型的更细致划分,咱们能够从表格中对全部数字类型有必定的了解。学习

数据类型定义 存储空间占用量 取值范围
TINYINT[(M)] 1个字节 带符号:-128~127(-2^{7}到2^{7}-1)
无符号:0~255(2^{8}-1)
SMALLINT[(M)] 2个字节 带符号:-32768~32767(-2^{15}到2^{15}-1)
无符号:0~65535(2^{16}-1)
MEDIUMINT[(M)] 3个字节 带符号:-8388608~8388607(-2^{23}到2^{23}-1)
无符号:0~16777215(2^{24}-1)
INT[(M)] 4个字节 带符号:-2147683648~2147683647(-2^{31}到2^{31}-1)
无符号:0~4294967295(2^{32}-1)
BIGINT[(M)] 8个字节 带符号:-128~127
无符号:0~255
DECIMAL([M[,D]]) 可变长度 其取值范围由M和D的值决定
FLOAT[(M)] 4个字节 最小非零值 :\pm 1.175494351E-38
最大非零值:\pm 1.175494351E-38
DOUBLE[(M)] 8个字节 最小非零值 :\pm 1.175494351E-38
最大非零值:\pm 1.175494351E-38
BIT[(M)] 1~4个字节 0到2^{M}-1

整数类型

整数类型用于存储整数,根据其存储的字节大小可分为TINYINTSMALLINTMEDIUMINT,INT,BIGINT,分别占用1,2,3,4,8个字节的大小,存储范围从 -2^{(N-1)}到2^{(N-1)}-1,其中N是类型的存储空间的位数(bit,1个字节8bit)。spa

UNSIGNED

通常整数都支持正负值,不过可使用可选的属性UNSIGNED,使其不容许负值,这样的话,可使用存储的正数上限提升一倍,好比TINYINT的范围由-128~127变为0~255

CREATE TABLE test_int(
    id int unsigned not null
);
复制代码

AUTO_INCREMENT

对整数类型,在建立数据表时,能够指定AUTO_INCRMENT属性,让该字段能够变成一个能够自动增加的序列,如:

CREATE TABLE test_int(
    id INT UNSIGNED NOT NULL AUTO_INCRMENT PRIMARY KEY,
    name VARCHAR(32) NOT NULL
);
复制代码

实数类型

实数类型分为浮点数定点数类型两种,定点数类型一种是精确值类型,DECIMAL就是定点数类型,浮点数是一种是近似值类型,FLOATDOUBLE就是浮点数类型。

浮点数类型存四舍五入的问题,所以在有须要精确运算的时候,可使用定点数或整数数据,避免计算偏差。

浮点数也可使用UNSIGNED属性,与整数同样,这会让浮点数变成所有是正数,不能支持负数。

浮点数也可使用AUTO_INCRMENT,这会让浮点数的表现与整数同样了。

位数类型

MySQL5.0之前,BIT类型是TINYINT的同义词,在MySQL 5.0之后,BIT类型是一种用于存储位字段值的类型。

BIT字段的值的格式为:0bval,b'val'B'val'val表示的是0或1组成的位字段常量值。

下面合法的BIT类型常量值:

0b11111
b'11111'
B'11111'
复制代码

而下面则不合法的常量值:

0B'11111'
b11111
B11111
复制代码

使用BIT字段时,能够指定一个长度M,即BIT(M)M的取值为1~64,,因此BIT类型的字段占用1~4个字节的长度。

#示例表1
CREATE TABLE test_bit_1(
    id bit
);
#示例表2
CREATE TABLE test_bit_2(
    id bit(8)
);
复制代码

上面的示例表1中,咱们没有指定M,因此默认值为1,即咱们只能向示例表1插入1个位值。

# 正确
INSERT INTO test_bit_1 VALUES(B1);
# 错误
INSERT INTO test_bit_1 VALUES(B11);
#正确
INSERT INTO test_bit VALUES(B11111111);
#正确
INSERT INTO test_bit VALUES(B000011111111);
# 错误
INSERT INTO test_bit VALUES(B000111111111);
复制代码

字符串类型

字符串类型是MySQL中最经常使用的数据类型,也是比较灵活的数据类型,学习字符串数据,也会讨论到字符集与转义字符等知识,由于比较复杂。

MySQL数据库中,字符串的字段值可使用双引号("")或单引号('')来括起来,好比:

'test'
"mysql"
复制代码

若是字符串值里面自己就包含双引号或单引号时,若是只包含单引号,则可使用双引号来引用字符串,反引亦然,而若是一个字符串里面同时包含单双引号时,也可使用反斜杠(\)进行转义,好比:

"I'm Programmer"
'He is "Programmer"'
'I\'m Programmer' 复制代码

下面的表格所展现的MySQL支持的全部字符串数据类型:

数据类型定义 存储空间占用量 最大长度
BINARY([M]) M个字节 M个字节
VARBINARY([M]) M个字节 L+1或L+2个字节
CHAR([M]) M个字符 M*w个字节
VARCHAR([M]) M个字符 L+1或L+2个字节
TINYBLOB 2^{32}-1个字节 L+1个字节
BLOB 2^{32}-1个字节 L+2个字节
MEDIUMBLOB 2^{32}-1个字节 L+3个字节
LONGBLOB 2^{32}-1个字节 L+4个字节
TINYTEXT 2^{8}-1个字符 L+1个字节
TEXT] 2^{16}-1个字符 L+2个字节
MEDIUMBLOB 2^{24}-1个字符 L+3个字节
LONGTEXT 2^{32}-1个字符 L+4个字节
SET('value1','value2',.....) 1或2个字节 64个成员
ENUM('value1','value2',.....) 1,2,3,4或8个字节 65535个成员

MySQL的字符串数据类型能够分为二进制字符串类型非二进制字符串类型两种,所以上面表格中的数据类型,还能够这样划分同样:

二进制字符串类型 非二进制字符串类型
BINARY CHAR
VARBINARY VARCHAR
TINYBLOB TINYTEXT
BLOB TEXT
MEDIUMBLOB MEDIUMTEXT
LONGBLOB LONGTEXT

二进制字符串类型用于存储二进制数据,其存储的尺寸用字节数来计算,而非二进制字符串用于保存其余字符串数据,其存储的尺寸用字符数来计算,其存储的长度能够经过在类型跟一个参数M来指定,如:

CREATE TABLE test_string(
    a BINARY(20),
    b CHAR(20)
);
复制代码

上面的示例数据表中,字段a是用于二进制数据,表示能够存储20个字节,而字段b存储非进制数据类型,表示能够存储20个字符。

对于非二进制字符串,在存储和解析时,还须要指定属于什么字符集和排序方式,不一样的字符集与排序方式二进制字符串类型的存储空间与比较方式。

关于字符集和排序方式的知识,之后有机会再讨论。

CHAR与VARCHAR

CHARVARCHAR在于,CHAR是定长字符串数据类型,而VARCHAR是可变长度的字符串数据类型。

CHAR的长度取值范围是1~255,默认值1,但CHAR(0)是合法,占用1个位,表示空字符串。

VARCHAR的取值范围是1~65535,不过VARCHAR的最大长度通常小于65535,所以MySQL中数据行的最大长度也是65535,况且VARCHAR还须要额外两个字节来记录其目前的存储长度。

BINARY与VARBINARY

BINARYVARBINARY的区别与CHARVARCHAR的区别是相似的。

BLOB家族与TEXT家族

BLOB是包含TINYBLOB,BLOB,MEDIUMBLOB,LONGBLOB系列数据类型的家族,用于存储二进制字符串,好比图片、声音等数据,而TEXT是包含TINYTEXT,TEXT,MEDIUMTEXT,LONGTEXT系列数据类型的家族用于存储非二进制字符串,因此TEXT系列的类型存储与解析与字符集有关。

使用MEMORY存储引擎的数据表不支持BLOBTEXT这两种数据类型。

ENUM与SET

ENUM是一种特殊的字符串类型,占用1或2个字节,也就是说ENUM类型能够设置65535个成员,ENUM类型与通常的字符串类型不一样,设置为ENUM类型的字段,只能存储预先定义好的字符串值。

以下所示,咱们建立一个users表,该表有一个定义为ENUM类型的gender字段:

CREATE TABLE users(
    id int not null,
    username varchar(32) not null,
    gender enum('f','m')
);
复制代码

下面的语句能够正确地写入数据表:

INSERT INTO users values(1,'test_1','f');
INSERT INTO users values(2,'test_2','m');
复制代码

而下面写入了一个gender字段未定义的值

INSERT INTO users values(3,'test_3','d');
复制代码

因此会报以下所示的错误:

ERROR 1265 (01000): Data truncated for column 'gender' at row 1
复制代码

ENUM同样,SET也是一种特殊的字符串类型,而且同样只能存储预先定义好的字符串值,SET根据预先定义值的数值会占用1,2,4或8个字节,但只能存储64个成员。

时间与日期类型

MySQL为存储时间与日期提供了YEARDATETIMEDATETIMETIMESTAMP等数据类型,分别占用1,3,3,8,4个字节的长度。

类型定义 取值范围 占用存储空间
DATE '1000-01'到'9999-12-31' 3个字节
TIME '-838:59:59'到'838:59:59' 3个字节
DATETIME '1000-01-01 00:00:00'到'9999-12-31 23:59:59' 8个字节
TIMESTAMP '1970-01-01 00:00:00'到'2038-01-19 03:14:07' 4个字节
YEAR([M]) 1901到2155 1个字节

DATE,TIME,DATETIME

DATE数据类型表示日期的值,占用3个字节,其取值范围为1000-01-01~9999-12-31,默认零值为0000-00-00

TIME类型占用3个字节,其取值范围是'-838:59:59'到'838:59:59',注意TIME类型并非表示时分秒,而表示逝去的一段时间,即表示两个事件之间的时间间隔,因此TIME类型能够为负值。

当咱们从数据表中查询TIME类型时,其显示格式为:

hh:mm:ss或hhh:mm:ss
复制代码

当咱们写入TIME类型字段值的时候,有些要注意的地方:

当咱们写入11:30时,会被处理为11:30:00,当咱们写入1122时,会被处理为00:11:22。

默认状况下,位于TIME范围以外但有效的值将被裁剪到该范围的最近端点。例如,“-850:00:00”和“ 850:00:00”被转换为“ -838:59:59”和“ 838:59:59”。无效的TIME值将转换为“ 00:00:00”。请注意,因为“ 00:00:00”自己就是有效的TIME值,所以没法经过表中存储的值“ 00:00:00”来判断原始值是否指定为“ 00”: 00:00'或是否无效。

DATETIME数据类型则是DATETIME两个种数据类型的组合。

TIMESTAMP

TIMESTAMP数据类型是用于保存日期与时间的组合值的,与时区相关,默认是以UTC(世界标准时间)的格式存储的,其取值范围是1970-01-01 00:00:002038-01-29 03:14:07,这也是4个字节所能表达的长度,因此TIMESTAMP占用4个字节,当咱们从数据中查询TIMESTAMP的数据列,会根据咱们当前的时区自动转换值。

YEAR

YEAR占用一个字节,在声明时,能够指定一个宽度MM的取值只能是4,即YEAR类型有两种写法,YEARYEAR(4),其取值范围1901~2155

若是咱们只须要存储年份,并且年份刚在落在YEAR的取值范围内,那咱们应该使用YEAR类型,由于若是咱们本身存储一个年份时,至少须要使用SMALLINT类型,这样会占用两个字节,而YEAR只占用一个字节。

JSON数据类型

MySQL5.7.8版本开始就支持存储原生的JSON类型的数据,咱们能够MySQL中存储JSON对象JSON数组JSON数据并非以字符串的形式存储,而是使用一种容许快速读取文本元素的内部二进制格式进行存储的,在JSON数据列中插入或者更新的时候将会自动验证JSON文本数据是否正确,未经过验证的文本将产生一个错误信息。

JSON数组是以中括号([])包含起来,并使用逗号隔的列表,其格式以下所示:

["abc", 10, null, true, false]
复制代码

JSON对象包含多个key-value,使用花括号({})包括起来并用逗号分隔的数据类型,其格式以下所示:

{"k1": "value", "k2": 10}
复制代码

另外,与BLOBTEXT类型同样,设置为JSON类型的字段时不能设置默认值,其默认值只能为NULL,因此下面的语句是错误的:

CREATE TABLE test_json(
    t json NOT NULL DEFAULT ''
);
复制代码

运行上面的建表语句,MySQL会提示下面所示的错误:

ERROR 1101 (42000): BLOB, TEXT, GEOMETRY or JSON column 't' can't have a default value 复制代码

下面的语句才是正确的:

CREATE TABLE test_json(
    t json not null
);
复制代码

JSON类型的存储长度与LONGBLOBLONGTEXT类型长度相同,固然最大的长度不能超过max_allowed_packet系统变量设置的值。

咱们能够下面的语句往上面的数据插入数据:

INSERT INTO test_json VALUES('{"key1": "value1", "key2": "value2"}');
复制代码

除了提供JSON数据类型,MySQL提供了许多能够操做JSON数据的函数,下面这些函数的说明:

函数 简介说明
JSON_APPEND() 将数据附加到JSON文档
JSON_ARRAY() 建立一个JSON数组
JSON_ARRAY_APPEND() 将数据附加到JSON文档
JSON_ARRAY_INSERT() 插入JSON数组
JSON_CONTAINS() JSON文档是否在路径中包含特定对象
JSON_CONTAINS_PATH() JSON文档是否在路径中包含任何数据
JSON_DEPTH() JSON文档的最大深度
JSON_EXTRACT() 从JSON文档返回数据
JSON_INSERT() 插入一个值到JSON文档中
JSON_KEYS() 将JSON文档的key提取为一个数组
JSON_LENGTH() JSON文档中的元素数
JSON_MERGE() 合并JSON文档
JSON_MERGE_PRESERVE() 合并JSON文档,保留重复的键
JSON_OBJECT() 建立一个JSON对象
JSON_PRETTY() 以易于阅读的格式打印JSON文档
JSON_QUOTE() 引用JSON文档
JSON_REMOVE() 从JSON文档中移除数据
JSON_REPLACE() 替换JSON文档中的现有值并返回结果
JSON_SEARCH() 查找全部指定值的位置
JSON_SET() 将数据插入JSON文档
JSON_STORAGE_SIZE() 用于存储JSON文档的二进制表示形式的空间
JSON_TYPE() 返回JSON类型:对象或数组
JSON_UNQUOTE() 取消引用JSON值
JSON_VALID() 验证JSON数据是否有效

JSON函数的简单示例:

# 判断JSON类型
mysql> SELECT JSON_TYPE('["a", "b", 1]');
+----------------------------+
| JSON_TYPE('["a", "b", 1]') |
+----------------------------+
| ARRAY                      |
+----------------------------+

# 建立JSON数组
mysql> SELECT JSON_ARRAY('a', 1, NOW());
+----------------------------------------+
| JSON_ARRAY('a', 1, NOW())              |
+----------------------------------------+
| ["a", 1, "2015-07-27 09:43:47.000000"] |
+----------------------------------------+
复制代码

上面的一些示例比较简单,对于这些函数的使用,咱们能够在实际的使用中慢慢探索。

如何选择数据类型

上面咱们介绍了这么多种数据类型,那到底应该如何选择数据类型呢?对于数据类型的选择,通常仍是要遵循如下几个原则:

更小的一般更好

数据越小,占用的空间就越小,查询的速度也就越快,占用的内存与CPU就更少,不过也不要所以就错误地选择了更小的数据类型,而致使数据溢出,毕竟在MySQL,修改数据类型是比较麻烦的事情,尤为是对已经有大量数据的数据表进行数据类型修改。

简单就好

一样,也简单的类型越好,查询与写入的速度也就越快。

避免使用NULL

不少的数据类型的默认值就是NULL,因此不少数据列能够把NULL做为空值,不过通常状况下,最好把数据列设置为NOT NULL,除非你真的须要把数据列设置为NULL。

由于容许为NULL的数据列,在索引处理方面复杂,并且须要额外的空间来存储。

小结

做为一个成熟的关系型数据库管理系统,MySQL支持了许多经常使用数据类型,方便咱们根据不一样的业务进行挑选,对于这些数据类型,咱们没必要死记硬背,不过在挑选数据类型时,仍是须要对不一样数据类型的存储空间长度,默认值,取值范围有必定的了解,才能挑选出最节省空间也最高效的数据类型。


若是你以为文章不错,欢迎扫码关注,你的关注就是我写做的最大动力

相关文章
相关标签/搜索