浅析MySQL数据类型

图片发自简书App

本文基于MySQL5.6版本进行描述
从大的方面来讲,MySQL的数据类型分为4种

  • 数值类型
  • 日期和时间
  • 字符串类型
  • 空间数据类型

为便于后续文章标记,先罗列下类型描述。就像是数学公式一样,先描述字母代表的含义。

  • M 对于数值类型,代表最大显示宽度;对于浮点型或者定点类型数据,代表可以存储的总位数(精度);对于字符串类型,代表最大长度。M的最大值取决于具体的数据类型。
  • D 适用于浮点型或定点型数据,代表小数点后面的位数。最大取值为30,但不能超过M-2。
  • fsp 适用于日期时间类型数据。表示小数秒精度,即秒小数点后面的数值位数。如果指定这个值,必须在0到6范围内。省略默认精度为0。(标准的SQL默认值为6)
  • [] 中括号内的值代表可选项。

数值类型

数值类型中,M表示最大可显示的宽度。最大显示宽度是255。

BIT[(M)]

M的取值范围是[1,64],如果不指定M的话,默认值为1。

TINYINT[(M)] [UNSIGNED] [ZEROFILL]

一种微小的整型,有符号取值范围是[-128,127],无符号取值范围是[0,256]。占用一字节。

BOOL BOOLEAN

这两个类型和TINYINT(1)是等价的。0是false,非0是true。请看例子

mysql> SELECT IF(0, 'true', 'false');
+------------------------+
| IF(0, 'true', 'false') |
+------------------------+
| false                  |
+------------------------+

mysql> SELECT IF(1, 'true', 'false');
+------------------------+
| IF(1, 'true', 'false') |
+------------------------+
| true                   |
+------------------------+

mysql> SELECT IF(2, 'true', 'false');
+------------------------+
| IF(2, 'true', 'false') |
+------------------------+
| true                   |
+------------------------+

大写的TRUE和FALSE代表1和0。请看例子

mysql> SELECT IF(0 = FALSE, 'true', 'false');
+--------------------------------+
| IF(0 = FALSE, 'true', 'false') |
+--------------------------------+
| true                           |
+--------------------------------+

mysql> SELECT IF(1 = TRUE, 'true', 'false');
+-------------------------------+
| IF(1 = TRUE, 'true', 'false') |
+-------------------------------+
| true                          |
+-------------------------------+

mysql> SELECT IF(2 = TRUE, 'true', 'false');
+-------------------------------+
| IF(2 = TRUE, 'true', 'false') |
+-------------------------------+
| false                         |
+-------------------------------+

mysql> SELECT IF(2 = FALSE, 'true', 'false');
+--------------------------------+
| IF(2 = FALSE, 'true', 'false') |
+--------------------------------+
| false                          |
+--------------------------------+

这后两个的结果是因为2既不等于1也不等于0

SMALLINT[(M)] [UNSIGNED] [ZEROFILL]

一种小整型。有符号取值范围是[-32768,32767],无符号取值范围是[0,65535]。占用两字节。

MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL]

一种中等大小的整型。有符号取值范围是[-8388608,8388607],无符号取值范围是[0,16777215]。占用三字节。

INT[(M)] [UNSIGNED] [ZEROFILL]

一种正常大小的整型。有符号取值范围是[-2147483648,2147483647],无符号取值范围是[0,4294967295]。占用四字节。

INTEGER[(M)] [UNSIGNED] [ZEROFILL]

这个类型等价于INT

BIGINT[(M)] [UNSIGNED] [ZEROFILL]

长整型。有符号取值范围是[-9223372036854775808,9223372036854775807],无符号取值范围是[0,18446744073709551615]。占用八字节。
需要注意以下几点

  • 所有的数值运算是通过BIGINT或者DOUBLE实现的。不要使用超过9223372036854775807 (63 bits)的无符号整数,如果超过这个数值,可能有精度损失。
    在以下几种场景,mysql可以处理:
  1. 在BIGINT列使用integers 存储大的无符号数;
  2. 当col_name 指代BIGINT列时,使用函数MAX(col_name ), MIN(col_name );
  3. 在两个integers类型上使用四则运算(+,-,*,...)
  • 你可以使用字符串给BIGINT列赋值,mysql会在写入时做类型转换。
  • 在两个integers类型上使用四则运算时要注意类型溢出,当结果大于9223372036854775807时,会得到不可预期的结果。

DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL]

定点类型。M代表所有数值的位数,D代表小数点后面的位数。M不包含小数点和负号。如果不指定D,表示没有小数部分。M的最大取值为65,默认值为10;D的最大取值为30,默认值为0。
如果指定了UNSIGNED,表示不允许负数。
所有在DECIMAL列上的四则运算(+,-,*,/)都是基于65位精度。

DEC[(M[,D])] [UNSIGNED] [ZEROFILL], NUMERIC[(M[,D])] [UNSIGNED] [ZEROFILL], FIXED[(M[,D])] [UNSIGNED] [ZEROFILL]
这些类型与DECIMAL等价。其中FIXED类型可与其他数据库兼容。

FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]
单精度浮点型。M代表所有数值的位数,D代表小数点后面的位数。如果不指定M和D的话,存储的值默认值取决于硬件支持情况。单精度浮点数精确到小数点后7位。
如果指定了UNSIGNED,表示不允许负数。
使用FLOAT可能会遇到不可预期的问题,因为FLOAT的所有运算在MySQL内部使用的是双精度。

DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]

双精度浮点型。M代表所有数值的位数,D代表小数点后面的位数。如果不指定M和D的话,存储的值默认值取决于硬件支持情况。双精度浮点数精确到小数点后15位。
如果指定了UNSIGNED,表示不允许负数。

DOUBLE PRECISION[(M,D)] [UNSIGNED] [ZEROFILL], REAL[(M,D)] [UNSIGNED] [ZEROFILL]

这些类型与DOUBLE等价。有个例外是:如果开启了 REAL_AS_FLOAT SQL模式,REAL与FLOAT等价

FLOAT(p) [UNSIGNED] [ZEROFILL]

浮点型数值。p表示精度,单位是比特。在MySQL中,这个值仅仅被当做区分FLOAT和DOUBLE。当p取值范围在[0,24]时,表示缺省M和D的FLOAT类型;当p取值范围在[25,53]时,表示缺省M和D的DOUBLE类型。
提供FLOAT(p)语法仅仅是为了适配ODBC。

日期和时间类型

本节对于DATE和DATETIME的取值范围描述时,支持仅仅意味着这些值可以工作,但是不完全保证。
MySQL 5.6.4及以上版本,对于 TIME, DATETIME以及TIMESTAMP类型支持小数秒,可达到微秒(秒小数点后6位)级别的精度。使用type_name(fsp)这种语法定义小数秒,其中type_name可以是TIME, DATETIME以及TIMESTAMP,fsp代表小数位的精度。例子:

CREATE TABLE t1 (t TIME(3), dt DATETIME(6));

fsp的有效取值范围是[0,6],如果不指定的话,默认值是0,代表没有小数秒部分(和标准的SQL不一样,这是为了适配老版本的MySQL)。

MySQL 5.6.5引入了扩展的可自动初始化和更新的时间类型。表中的任何TIMESTAMP列都可以自动初始化和更新,而不是老版本MySQL的仅仅支持一个。另外,DATATIME也支持这些特性(可自动初始化和更新)。

DATE

日期。支持的取值范围是'1000-01-01' 到'9999-12-31'。MySQL使用'YYYY-MM-DD'格式来显示DATE类型的值,可以通过字符串或者是整数进行赋值。

DATETIME[(fsp)]

日期和时间的结合。其支持的取值范围是 '1000-01-01 00:00:00.000000' 到 '9999-12-31 23:59:59.999999'。MySQL使用'YYYY-MM-DD HH:MM:SS[.fraction]'格式来显示DATETIME类型的值,可以通过字符串或者是整数进行赋值。
对于MySQL 5.6.4版本,fsp是可选值,取值0到6之间,代表小数秒的精度。缺省默认是0,代表没有小数秒。
对于MySQL 5.6.5版本,可以使用DEFAULT以及ON UPDATE来修饰DATETIME,表示支持自动初始化和更新。

TIMESTAMP[(fsp)]

时间戳。取值范围是'1970-01-01 00:00:01.000000' UTC 到 '2038-01-19 03:14:07.999999' UTC。TIMESTAMP是用整型秒存储,代表'1970-01-01 00:00:00' UTC到现在经历的时间。
注意TIMESTAMP无法表示时间'1970-01-01 00:00:00',因为根据上面的描述,这个时间应该是等价于0(经过了0秒),但是0又被'0000-00-00 00:00:00'占用了。所以这是个悖论,干脆定义为无法表示'1970-01-01 00:00:00'。
自MySQL 5.6.4版本,MySQL可以使用fsp表示小数秒。取值0到6,默认值为0表示没有小数秒。
MySQL服务端处理TIMESTAMP取决于explicit_defaults_for_timestamp这个系统参数。
如果这个explicit_defaults_for_timestamp系统参数被激活,表示对于任何使用DEFAULT CURRENT_TIMESTAMP 或者
ON UPDATE CURRENT_TIMESTAM修饰的TIMESTAMP列,都没有自动赋值功能
。必须手动赋值,另外任何未显式指定 NOT NULL的列,都允许NULL。
如果这个explicit_defaults_for_timestamp系统参数未被激活,MySQL服务端对TIMESTAMP 做如下处理:

  • 除非指定值,否则表中的首个定义了自动赋值的TIMESTAMP列,会被自动赋值为服务端最近修改的时间。当然你也可以明确指定NULL对其赋值来把这个列更新为当前时间,但是这个是取决于TIMESTAMP列没有指定允许NULL值的情况下。
  • 可以使用DEFAULT CURRENT_TIMESTAMP and ON UPDATE为TIMESTAMP列定义自动初始化和自动更新。默认情况下,第一列TIMESTAMP肯定有这些特性。对于MySQL 5.6.5版本,任何TIMESTAMP列都可以有这些特性。MySQL 5.6.5之前版本,最多只能有一列才有这个特性。可以为第一列禁止此特性,而将它们分配给其他的TIMESTAMP列。
  • explicit_defaults_for_timestamp这个系统参数只有在MySQL 5.6.5版本。

TIME[(fsp)]

时间。取值范围是'-838:59:59.000000' 到 '838:59:59.000000'。MySQL使用'HH:MM:SS[.fraction]'格式显示。支持字符串和数字为其赋值。
自MySQL 5.6.4版本,MySQL可以使用fsp表示小数秒。取值0到6,默认值为0表示没有小数秒。

YEAR[(2|4)]

两位或者是四位表示的年,默认是四位表示。
四位的取值是1901 到 2155,还有0000。
两位的取值是70到69。代表1970到2069.
MySQL使用 YYYY 或者 YY格式表示年,可以使用字符串或者整数赋值。

  • 对于时间类型, SUM() 和 AVG() 函数不起使用。如果要用,得转换格式:
SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(time_col))) FROM tbl_name;
SELECT FROM_DAYS(SUM(TO_DAYS(date_col))) FROM tbl_name;

字符串类型

在任何场景,MySQL在使用CREATE TABLE 以及 ALTER TABLE 操作的时候,会自动把string类型转换为目标数据类型。
许多字符串类型字段定义的时候,可以包含属性描述:字符集或列的排序规则。这些属性也可用于CHAR, VARCHAR, TEXT, ENUM, SET。

CREATE TABLE t
(
    c1 VARCHAR(20) CHARACTER SET utf8,
    c2 TEXT CHARACTER SET latin1 COLLATE latin1_general_cs
);

这段代码创建了表。此表定义创建一个名为c1的列,该列具有字符集utf8,该字符集具有默认排序规则,名为c2的列具有latin1字符集和区分大小写的排序规则。
指定 CHARACTER SET为binary属性时,会导致类型转变。
假设有如下代码

CREATE TABLE t
(
  c1 VARCHAR(10) CHARACTER SET binary,
  c2 TEXT CHARACTER SET binary,
  c3 ENUM('a','b','c') CHARACTER SET binary
);

这段代码创建表之后,结果等价于下面这段代码

CREATE TABLE t
(
  c1 VARBINARY(10),
  c2 BLOB,
  c3 ENUM('a','b','c') CHARACTER SET binary
);
  • 即 CHAR 变成BINARY;VARCHAR 变成VARBINARY;TEXT 变成BLOB。
  • BINARY是这个的简写:默认字符集,同时指定binary排序规则。
  • ASCII是这个的简写:CHARACTER SET latin1
  • UNICODE是这个的简写: CHARACTER SET ucs2
    字符列的比较和排序规则取决于列排序属性。

[NATIONAL] CHAR[(M)] [CHARACTER SET charset_name] [COLLATE collation_name]

一个固定长度的字符串,在存储时总是用空格填充指定的长度。 M代表字符的列长度。 M的范围是0到255.如果省略M,则长度为1。

  • 除非启用了PAD_CHAR_TO_FULL_LENGTH SQL模式,否则在获取CHAR值时删除尾随空格。
    MySQL 允许你创建CHAR(0)。这个可以用于如下场景:必须有这一列,但是不使用这个列。比如预留列可以使用这个。这样仅仅占用一个比特位的存储空间,取值有:NULL 和''(空字符串)。

[NATIONAL] VARCHAR(M) [CHARACTER SET charset_name] [COLLATE collation_name]

可变长度的字符串。 M代表字符中的最大列长度。 M的范围是0到65535。 VARCHAR的有效最大长度取决于最大行大小(65,535字节,在所有列中共享)和使用的字符集。 例如,utf8字符每个字符最多可能需要三个字节,因此使用utf8字符集的VARCHAR列可以被声明为最多21844个字符。
MySQL使用1到2字节前缀存储字符串长度。当长度小于255时采用1字节存储长度;当长度大于255时使用2字节存储长度。

  • MySQL并不移除VARCHAR列的结尾空格,VARCHAR默认预定义的字符集为utf8。

BINARY[(M)]

BINARY和CHAR类似。只不过这个类型用于存储二进制格式的字节串。可选的M标识字节的长度,默认为1.

VARBINARY(M)

VARBINARY和VARCHAR类似。只不过这个类型用于存储二进制格式的字节串。可选的M标识字节的长度,默认为1.

TINYBLOB

TINYBLOB列的最大长度是255字节.每个TINYBLOB值使用1字节的长度前缀标识串的长度。

TINYTEXT [CHARACTER SET charset_name] [COLLATE collation_name]

TINYTEXT 列的最大长度是255字符.有效的长度可能小于255,因为可能包含多字节字符。每个TINYTEXT 值使用1字节的长度前缀标识串的长度。

BLOB[(M)]

BLOB列的最大长度是65535字节.每个BLOB值使用2字节的长度前缀标识串的长度。
可选的长度可以指定。指定长度之后,MySQL会使用最小能足够支撑指定长度的BLOB类型来创建列。

TEXT[(M)] [CHARACTER SET charset_name] [COLLATE collation_name]

TEXT列的最大长度是65535字符。有效的长度可能小于65535,因为可能包含多字节字符。每个TEXT值使用2字节的长度前缀标识串的长度。
可选的长度可以指定。指定长度之后,MySQL会使用最小能足够支撑指定长度的TEXT类型来创建列。

MEDIUMBLOB

MEDIUMBLOB列的最大长度是16777215字节.每个MEDIUMBLOB值使用3字节的长度前缀标识串的长度。

MEDIUMTEXT [CHARACTER SET charset_name] [COLLATE collation_name]

MEDIUMTEXT 列的最大长度是16777215字符。有效的长度可能小于16777215,因为可能包含多字节字符。每个MEDIUMTEXT 值使用3字节的长度前缀标识串的长度。

LONGBLOB

LONGBLOB列的最大长度是4294967295 or 4GB字节.最大长度取决于包的大小,协议,以及内存。每个LONGBLOB值使用4字节的长度前缀标识串的长度。

LONGTEXT [CHARACTER SET charset_name] [COLLATE collation_name]

LONGTEXT 列的最大长度是4294967295 or 4GB字符.有效的长度可能小于4294967295 ,因为可能包含多字节字符。最大长度取决于包的大小,协议,以及内存。每个LONGTEXT 值使用4字节的长度前缀标识串的长度。

ENUM('value1','value2',...) [CHARACTER SET charset_name] [COLLATE collation_name]

枚举值。一个字符串只能有一个取值。为这些其中之一: 'value1', 'value2', ..., NULL 或者是''错误值。
枚举值在MySQL内存采用整型表示。
枚举值最多有65535个元素(实际是少于3000)。一个表在其ENUM和SET列中可以有多于255个唯一的元素列表定义,被视为一个组。

SET('value1','value2',...) [CHARACTER SET charset_name] [COLLATE collation_name]

集合。一个字符串对象可以有0个或者多个值。为这些其中之一:'value1', 'value2', ...
集合在MySQL内部以整型表现。
SET列最多可以有64个不同的成员。 一个表在其ENUM和SET列中可以有多于255个唯一的元素列表定义,被视为一个组。

本文只是简要罗列MySQL的基本数据类型,空间类型未做描述。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 10,850评论 6 13
  • MySQL数据库对象与应用 2.1-MySQL数据类型 库建立好之后基本不动,和我们接触最频繁的是表. 建表就是声...
    极客圈阅读 2,125评论 0 8
  • MySQL技术内幕:SQL编程 姜承尧 第1章 SQL编程 >> B是由MySQL创始人之一Monty分支的一个版...
    沉默剑士阅读 2,404评论 0 3
  • 什么是数据库? 数据库是存储数据的集合的单独的应用程序。每个数据库具有一个或多个不同的API,用于创建,访问,管理...
    chen_000阅读 4,028评论 0 19
  • 同学人名诗歌 20170101 魏 天 兰 魏有美女劳作忙, 天不二更理红妆, 兰花扑鼻暗幽香, 白玉豆腐呈...
    如梦尘缘阅读 252评论 0 1