原创做者,公众号【程序员读书】,欢迎关注公众号,转载文章请注明出处哦。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
支持的数据类型有:数字类型
,字符串类型
(包括字符)、时间与日期类型
、空间类型
和JSON类型
,不一样数据类型有不一样的特性,咱们可从该类型的存储空间、取值范围、默认值、如何进行比较,是否能够索引等等方面对其进行学习。bash
注:空间数据类型在平时使用并不太经常使用,所以在咱们的文章中便不做介绍了。函数
MySQL
的数字类型可分为整数类型
、定点型类型
、浮点数类型
、位类型
四种类型,下面表格是这四种数据类型的更细致划分,咱们能够从表格中对全部数字类型有必定的了解。学习
数据类型定义 | 存储空间占用量 | 取值范围 |
---|---|---|
TINYINT[(M)] | 1个字节 | 带符号:-128~127(-2![]() ![]() 无符号:0~255(2 ![]() |
SMALLINT[(M)] | 2个字节 | 带符号:-32768~32767(-2![]() ![]() 无符号:0~65535(2 ![]() |
MEDIUMINT[(M)] | 3个字节 | 带符号:-8388608~8388607(-2![]() ![]() 无符号:0~16777215(2 ![]() |
INT[(M)] | 4个字节 | 带符号:-2147683648~2147683647(-2![]() ![]() 无符号:0~4294967295(2 ![]() |
BIGINT[(M)] | 8个字节 | 带符号:-128~127 无符号:0~255 |
DECIMAL([M[,D]]) | 可变长度 | 其取值范围由M和D的值决定 |
FLOAT[(M)] | 4个字节 | 最小非零值 :![]() 最大非零值: ![]() |
DOUBLE[(M)] | 8个字节 | 最小非零值 :![]() 最大非零值: ![]() |
BIT[(M)] | 1~4个字节 | 0到2![]() |
整数类型用于存储整数,根据其存储的字节大小可分为TINYINT
,SMALLINT
,MEDIUMINT
,INT
,BIGINT
,分别占用1,2,3,4,8个字节的大小,存储范围从 -2到2
-1,其中N是类型的存储空间的位数(bit,1个字节8bit)。spa
通常整数都支持正负值,不过可使用可选的属性UNSIGNED
,使其不容许负值,这样的话,可使用存储的正数上限提升一倍,好比TINYINT
的范围由-128~127
变为0~255
。
CREATE TABLE test_int(
id int unsigned not null
);
复制代码
对整数类型,在建立数据表时,能够指定AUTO_INCRMENT
属性,让该字段能够变成一个能够自动增加的序列,如:
CREATE TABLE test_int(
id INT UNSIGNED NOT NULL AUTO_INCRMENT PRIMARY KEY,
name VARCHAR(32) NOT NULL
);
复制代码
实数类型分为浮点数
和定点数
类型两种,定点数类型一种是精确值类型,DECIMAL
就是定点数类型,浮点数是一种是近似值类型,FLOAT
和DOUBLE
就是浮点数类型。
浮点数类型存四舍五入的问题,所以在有须要精确运算的时候,可使用定点数或整数数据,避免计算偏差。
浮点数也可使用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![]() |
L+1个字节 |
BLOB | 2![]() |
L+2个字节 |
MEDIUMBLOB | 2![]() |
L+3个字节 |
LONGBLOB | 2![]() |
L+4个字节 |
TINYTEXT | 2![]() |
L+1个字节 |
TEXT] | 2![]() |
L+2个字节 |
MEDIUMBLOB | 2![]() |
L+3个字节 |
LONGTEXT | 2![]() |
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
在于,CHAR
是定长字符串数据类型,而VARCHAR
是可变长度的字符串数据类型。
CHAR
的长度取值范围是1~255
,默认值1,但CHAR(0)是合法,占用1个位,表示空字符串。
而VARCHAR
的取值范围是1~65535,不过VARCHAR的最大长度通常小于65535,所以MySQL
中数据行的最大长度也是65535,况且VARCHAR
还须要额外两个字节来记录其目前的存储长度。
BINARY
与VARBINARY
的区别与CHAR
和VARCHAR
的区别是相似的。
BLOB
是包含TINYBLOB
,BLOB
,MEDIUMBLOB
,LONGBLOB
系列数据类型的家族,用于存储二进制字符串,好比图片、声音等数据,而TEXT
是包含TINYTEXT
,TEXT
,MEDIUMTEXT
,LONGTEXT
系列数据类型的家族用于存储非二进制字符串,因此TEXT
系列的类型存储与解析与字符集有关。
使用MEMORY
存储引擎的数据表不支持BLOB
和TEXT
这两种数据类型。
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
为存储时间与日期提供了YEAR
,DATE
,TIME
,DATETIME
,TIMESTAMP
等数据类型,分别占用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
数据类型表示日期的值,占用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
数据类型则是DATE
和TIME
两个种数据类型的组合。
TIMESTAMP数据类型是用于保存日期与时间的组合值的,与时区相关,默认是以UTC
(世界标准时间)的格式存储的,其取值范围是1970-01-01 00:00:00
到2038-01-29 03:14:07
,这也是4个字节所能表达的长度,因此TIMESTAMP
占用4个字节,当咱们从数据中查询TIMESTAMP
的数据列,会根据咱们当前的时区自动转换值。
YEAR
占用一个字节,在声明时,能够指定一个宽度M
,M
的取值只能是4,即YEAR
类型有两种写法,YEAR
和YEAR(4)
,其取值范围1901~2155
若是咱们只须要存储年份,并且年份刚在落在YEAR
的取值范围内,那咱们应该使用YEAR
类型,由于若是咱们本身存储一个年份时,至少须要使用SMALLINT
类型,这样会占用两个字节,而YEAR
只占用一个字节。
MySQL
从5.7.8
版本开始就支持存储原生的JSON
类型的数据,咱们能够MySQL
中存储JSON对象
或JSON数组
。JSON
数据并非以字符串的形式存储,而是使用一种容许快速读取文本元素的内部二进制格式进行存储的,在JSON数据列
中插入或者更新的时候将会自动验证JSON
文本数据是否正确,未经过验证的文本将产生一个错误信息。
JSON数组是以中括号([]
)包含起来,并使用逗号隔的列表,其格式以下所示:
["abc", 10, null, true, false]
复制代码
JSON对象包含多个key-value,使用花括号({}
)包括起来并用逗号分隔的数据类型,其格式以下所示:
{"k1": "value", "k2": 10}
复制代码
另外,与BLOB
和TEXT
类型同样,设置为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类型
的存储长度与LONGBLOB
,LONGTEXT
类型长度相同,固然最大的长度不能超过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做为空值,不过通常状况下,最好把数据列设置为NOT NULL,除非你真的须要把数据列设置为NULL。
由于容许为NULL的数据列,在索引处理方面复杂,并且须要额外的空间来存储。
做为一个成熟的关系型数据库管理系统,MySQL
支持了许多经常使用数据类型,方便咱们根据不一样的业务进行挑选,对于这些数据类型,咱们没必要死记硬背,不过在挑选数据类型时,仍是须要对不一样数据类型的存储空间长度,默认值,取值范围有必定的了解,才能挑选出最节省空间也最高效的数据类型。
若是你以为文章不错,欢迎扫码关注,你的关注就是我写做的最大动力