美文网首页
浅析MySQL数据类型

浅析MySQL数据类型

作者: 黑哥儿666 | 来源:发表于2017-11-18 03:01 被阅读127次
    浅析MySQL数据类型

    本文基于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的基本数据类型,空间类型未做描述。

    相关文章

      网友评论

          本文标题:浅析MySQL数据类型

          本文链接:https://www.haomeiwen.com/subject/wkekvxtx.html