首页 > 数据库 >MySQL------数据类型重点关注

MySQL------数据类型重点关注

时间:2023-01-31 18:12:46浏览次数:62  
标签:存储 字节 数据类型 00 类型 MySQL ------ 长度

整数类型

整数类型 字节 有符号数取值范围 无符号数取值范围
TINYINT 1 - 128 ~ 127 0 ~ 255
SMALLINT 2 - 32768 ~ 32767 0 ~ 65535
MEDIUMINT 3 - 8388608 ~ 8388607 0 ~ 16777215
INT、INTEGER 4 - 2147483648 ~ 2147483647 0 ~ 4294967295
BIGINT 8 -9223372036854775808~9223372036854775807 0~18446744073709551615

可选属性:

  1. UNSIGNED:无符号类型(非负)

  2. ZEROFILL:0填充

  3. (M):宽度,取值范围是( 0 , 255 ),例如,int( 5 )。

    该项功能需要配合“ZEROFILL”使用,表示用“ 0 ”填满宽度,否则指定显示宽度无效。

    从MySQL 8. 0. 17 开始,整数数据类型不推荐使用显示宽度属性。

    在 int(M) 中,M 的值跟 int(M) 所占多少存储空间并无任何关系。 int(3)、int(4)、int(8) 在磁盘上都是占用 4 bytes 的存储空间。也就是说,int(M),必须和UNSIGNED ZEROFILL一起使用才有意义。如果整数值超过M位,就按照实际位数存储。只是无须再用字符 0 进行填充。

    如果某列是ZEROFILL,那么MySQL会自动为当前列添加UNSIGNED属性。

    如果指定了ZEROFILL只是表示不够M位时,用 0 在左边填充,如果超过M位,只要不超过数据存储范围即可。

浮点数类型

MySQL支持的浮点数类型,分别是 FLOAT(4字节)、DOUBLE(8字节)、REAL

REAL默认就是 DOUBLE。如果你把 SQL 模式设定为启用“REAL_AS_FLOAT”,那 么,MySQL 就认为REAL 是 FLOAT。如果要启用“REAL_AS_FLOAT”,可以通过以下 SQL 语句实现:

SET sql_mode = “REAL_AS_FLOAT”;

从MySQL 8. 0. 17 开始,FLOAT(M,D) 和DOUBLE(M,D)用法在官方文档中已经明确不推荐使用 ,将来可能被移除。另外,关于浮点型FLOAT和DOUBLE的UNSIGNED也不推荐使用了,将来也可能被移除。

浮点数类型有个缺陷,就是不精准。MySQL 用DECIMAL表示精准浮点类型。

定点数类型

【强制】小数类型为 DECIMAL,禁止使用 FLOAT 和 DOUBLE。

  • 说明:在存储的时候,FLOAT 和 DOUBLE 都存在精度损失的问题,很可能在比较值的时候,得到不正确的结果。如果存储的数据范围超过 DECIMAL 的范围,建议将数据拆成整数和小数并分开存储。
数据类型 字节数 含义
DECIMAL(M,D),DEC,NUMERIC M+2字节 有效范围由M和D决定

使用 DECIMAL(M,D) 的方式表示高精度小数。其中,M被称为精度,D被称为标度。0<=M<=65,0<=D<=30,D<M。例如,定义DECIMAL(5,2)的类型,表示该列取值范围是-999.99~999.99。

  • DECIMAL(M,D)的最大取值范围与DOUBLE类型一样 ,但是有效的数据范围是由M和D决定的。

  • 定点数在MySQL内部是以字符串的形式进行存储,这就决定了它一定是精准的。

  • 当DECIMAL类型不指定精度和标度时,其默认为DECIMAL(10,0)。当数据的精度超出了定点数类型的精度范围时,则MySQL同样会进行四舍五入处理。

  • 浮点数 vs 定点数

    • 浮点数相对于定点数的优点是在长度一定的情况下,浮点类型取值范围大,但是不精准,适用于需要取值范围大,又可以容忍微小误差的科学计算场景(比如计算化学、分子建模、流体动力学等)
    • 定点数类型取值范围相对小,但是精准,没有误差,适合于对精度要求极高的场景 (比如涉及金额计算的场景)

日期与时间类型

类型 名称 字节 日期格式 最小值 最大值
YEAR 1 YYYY或YY 1901 2155
TIME 时间 3 HH:MM:SS - 838 : 59 : 59 838 : 59 : 59
DATE 日期 3 YYYY-MM-DD 1000 - 01 - 01 9999 - 12 - 03
DATETIME 日期 时间 8 YYYY-MM-DD HH:MM:SS 1000 - 01 - 01 00 : 00 : 00 9999 - 12 - 31 23 : 59 : 59
TIMESTAMP 日期 时间 4 YYYY-MM-DD HH:MM:SS 1970 - 01 - 01 00 : 00 : 00 UTC 2038 - 01 - 19 03 : 14 : 07 UTC

TIME 的取值范围不是 - 23 : 59 : 59 ~ 23 : 59 : 59 。因为其不光表示一天之内的时间,而且可以用来表示一个时间间隔,这个时间间隔可以超过 24 小时。

YEAR

在MySQL中,YEAR有以下几种存储格式:

  • 以 4 位字符串或数字格式表示YEAR类型,其格式为YYYY,最小值为 1901 ,最大值为2155
  • 以 2 位字符串格式表示YEAR类型,最小值为 00 ,最大值为 99 。
    • 当取值为 01 到 69 时,表示 2001 到 2069 ;
    • 当取值为 70 到 99 时,表示 1970 到 1999 ;
    • 当取值整数的 0 或 00 添加的话,那么是 0000 年;
    • 当取值是日期/字符串的’ 0 ‘添加的话,是 2000 年。

从MySQL 5. 5. 27 开始, 2 位格式的YEAR已经不推荐使用 。YEAR默认格式就是“YYYY”,没必要写成YEAR( 4 ),从MySQL 8. 0. 19 开始,不推荐使用指定显示宽度的YEAR( 4 )数据类型。

DATE

  • YYYY-MM-DD格式或者YYYYMMDD格式表示的字符串日期,其最小取值为 1000 - 01 - 01 ,最大取值为9999 - 12 - 03 。YYYYMMDD格式会被转化为YYYY-MM-DD格式。

  • YY-MM-DD格式或者YYMMDD格式表示的字符串日期(不推荐)

    当年份取值为 00 到 69 时,会被转化为 2000 到 2069 ;当年份取值为70 到 99时,会被转化为 1970 到 1999

TIME

  • 可以使用带有冒号的字符串,比如’D HH:MM:SS‘、’HH:MM:SS‘、’HH:MM‘、’D HH:MM‘、’D HH‘或’SS‘格式,都能被正确地插入TIME类型的字段中。

    • 其中D表示天,其最小值为0,最大值为34。如果使用带有D格式的字符串插入TIME类型的字段时,D会被转化为小时,计算格式为D* 24 +HH。

    • 当使用带有冒号并且不带D的字符串表示时间时,表示当天的时间,比如12 : 10表示12:10:00,而不是00 :12 : 10 。

  • 可以使用不带有冒号的字符串或者数字,格式为’HHMMSS‘或者HHMMSS

    • 如果插入一个不合法的字符串或者数字,MySQL在存储数据时,会将其自动转化为 00 : 00 : 00 进行存储。

    • 比如1210,MySQL会将最右边的两位解析成秒,表示00 : 12 : 10 ,而不是 12 : 10 : 00 ,(注意与12:10的结果区分

  • 使用CURRENT_TIME()或者NOW(),会插入当前系统的时间。

DATETIME

  • YYYY-MM-DD HH:MM:SS格式或者YYYYMMDDHHMMSS格式的字符串插入DATETIME类型的字段时,最小值为 1000 - 01 - 01 00 : 00 : 00 ,最大值为 9999 - 12 - 03 23 : 59 : 59 。
    • 以YYYYMMDDHHMMSS格式的数字插入DATETIME类型的字段时,会被转化为YYYY-MM-DD HH:MM:SS格式。
  • YY-MM-DD HH:MM:SS格式或者YYMMDDHHMMSS格式的字符串插入DATETIME类型的字段时,两位数的年份规则符合YEAR类型的规则, 00 到 69 表示 2000 到 2069 ; 70 到 99 表示 1970 到 1999
  • 使用函数CURRENT_TIMESTAMP()NOW(),可以向DATETIME类型的字段插入系统的当前日期和时间。

TIMESTAMP

  • 存储数据的时候需要对当前时间所在的时区进行转换,查询数据的时候再将时间转换回当前的时区。因此,使用TIMESTAMP存储的同一个时间值,在不同的时区查询时会显示不同的时间

  • TIMESTAMP和DATETIME的区别:

    • TIMESTAMP存储空间比较小,表示的日期时间范围也比较小。

    • 底层存储方式不同,TIMESTAMP底层存储的是毫秒值,距离 1970 - 1 - 1 0 : 0 : 0 0 毫秒的毫秒值。

    • 两个日期比较大小或日期计算时,TIMESTAMP更方便、更快。

    • TIMESTAMP和时区有关。TIMESTAMP会根据用户的时区不同,显示不同的结果。而DATETIME则只能反映出插入时当地的时区,其他时区的人查看数据必然会有误差的。

    • 若存储的时间需要计算,则不建议使用DATETIME存储,而是使用TIMESTAMP

文本字符串类型

CHAR & VARCHAR

【强制】如果存储的字符串长度几乎相等,使用 CHAR 定长字符串类型。

【强制】VARCHAR 是可变长字符串,不预先分配存储空间,长度不要超过 5000 。如果存储长度大于此值,定义字段类型为 TEXT,独立出来一张表,用主键来对应,避免影响其它字段索引效率。

字符串(文本)类型 特点 长度 长度范围 占用的存储空间
CHAR(M) 固定长度 M 0 <= M <= 255 M个字节
VARCHAR(M) 可变长度 M 0 <= M <= 65535 (实际长度 + 1 ) 个字节
  • 如果保存时,数据的实际长度比CHAR类型声明的长度小,则会在右侧填充空格以达到指定的长度。当MySQL检索CHAR类型的数据时,CHAR类型的字段会去除尾部的空格。

    注意:当你故意插入一条数据为:“text ”,其尾部含有空格,将其插入CHAR类型的字段中后,则后面的空格也会被去除

  • 定义CHAR类型字段时,声明的字段长度即为CHAR类型字段所占的存储空间的字节数。

  • MySQL4.0版本以下,VARCHAR(20):指的是 20 字节,如果存放UTF8汉字时,只能存 6 个(每个汉字 3 字节) ;MySQL5.0版本以上,VARCHAR(20):指的是 20 字符。

  • 检索VARCHAR类型的字段数据时,会保留数据尾部的空格。VARCHAR类型的字段所占用的存储空间为字符串实际长度加 1 个字节。

哪些情况使用 CHAR 或 VARCHAR 更好 ?

类型 特点 空间上 时间上 适用场景
CHAR(M) 固定长度 浪费存储空间 效率高 存储不大,速度要求高
VARCHAR(M) 可变长度 节省存储空间 效率低 非CHAR的情况

情况 1 :存储很短的信息。比如门牌号码 101 ,201……这样很短的信息应该用char,因为varchar还要占个byte用于存储信息长度,本来打算节约存储的,结果得不偿失。

情况 2 :固定长度的。比如使用uuid作为主键,那用char应该更合适。因为他固定长度,varchar动态根据长度的特性就消失了,而且还要占个长度信息。

是否建议用UUID作为主键?详见:UUID 及其在 MySQL 中的使用

情况 3 :十分频繁改变的column。因为varchar每次存储都要有额外的计算,得到长度等工作,如果一个非常频繁改变的,那就要有很多的精力用于计算,而这些对于char来说是不需要的。

情况 4 :具体存储引擎中的情况:

  • MyISAM 数据存储引擎和数据列:MyISAM数据表,最好使用固定长度(CHAR)的数据列代替可变长度(VARCHAR)的数据列。这样使得整个表静态化,从而使数据检索更快,用空间换时间。
  • MEMORY 存储引擎和数据列:MEMORY数据表目前都使用固定长度的数据行存储,因此无论使用CHAR或VARCHAR列都没有关系,两者都是作为CHAR类型处理的。
  • InnoDB存储引擎,建议使用VARCHAR类型。因为对于InnoDB数据表,内部的行存储格式并没有区分固定长度和可变长度列(所有数据行都使用指向数据列值的头指针),而且 主要影响性能的因素是数据行使用的存储总量 ,由于CHAR平均占用的空间多于VARCHAR,所以除了简短并且固定长度的,其他考虑VARCHAR。这样节省空间,对磁盘I/O和数据存储总量比较好。

TEXT

文本字符串类型 特点 长度 长度范围 占用的存储空间
TINYTEXT 小文本、可变长度 L 0 <= L <= 255 L + 2 个字节
TEXT 文本、可变长度 L 0 <= L <= 65535 L + 2 个字节
MEDIUMTEXT 中等文本、可变长度 L 0 <= L <= 16777215 L + 3 个字节
LONGTEXT 大文本、可变长度 L 0 <= L<= 4294967295(相当于4GB) L + 4 个字节
  • 在向TEXT类型的字段保存和查询数据时,系统自动按照实际长度存储,不需要预先定义长度。这一点和VARCHAR类型相同。
  • 由于实际存储的长度不确定,MySQL 不允许 TEXT 类型的字段做主键 。遇到这种情况,你只能采用CHAR(M),或者 VARCHAR(M)。
  • TEXT文本类型,可以存比较大的文本段,搜索速度稍慢,因此如果不是特别大的内容,建议使用CHAR、VARCHAR来代替。
  • TEXT类型不用加默认值,加了也没用。
  • text和blob类型的数据删除后容易导致“空洞”,使得文件碎片比较多,所以频繁使用的表不建议包含TEXT类型字段建议单独分出去,单独用一个表

JSON 类型

-- ①
CREATE TABLE test_json(
js json
);
-- ②
INSERT INTO test_json (js)
VALUES ('{"name":"zhangsan", "age":18, "address":{"province":"guangdong","city":"shenzhen"}}');
-- ③
SELECT js -> '$.name' AS NAME,
	   js -> '$.age' AS age ,
	   js -> '$.address.province' AS province, 
	   js -> '$.address.city' AS city
FROM test_json;

-- 查询结果:
+----------+------+-----------+-----------+
| NAME | age | province | city |
+----------+------+-----------+-----------+
| "zhangsan" | 18 | "guangdong" | "shenzhen" |
+----------+------+-----------+-----------+
1 row in set (0.00 sec)

-- 可以看到列中的数据被引号包围。要删除引号,请使用内联路径运算符( ->>),如下所示:
SELECT js ->> '$.name' AS NAME,
	   js ->> '$.age' AS age ,
	   js ->> '$.address.province' AS province, 
	   js ->> '$.address.city' AS city
FROM test_json;

-- 查询结果:
+----------+------+-----------+-----------+
| NAME | age | province | city |
+----------+------+-----------+-----------+
| zhangsan | 18 | guangdong | shenzhen |
+----------+------+-----------+-----------+
1 row in set (0.00 sec)

通过“->”和“->>”符号,从JSON字段中正确查询出了指定的JSON数据的值。

ENUM类型

文本字符串类型 长度 长度范围 占用的存储空间
ENUM L 1 <= L <= 65535 1 或 2 个字节
  • 设置字段值时,ENUM类型只允许从成员中选取单个值,不能一次选取多个值。

  • 当ENUM类型包含 1 ~ 255 个成员时,需要 1 个字节的存储空间;

  • 当ENUM类型包含 256 ~ 65535 个成员时,需要 2 个字节的存储空间。

  • ENUM类型的成员个数的上限为 65535 个。

  • 插入的值:忽略大小写允许按照角标的形式获取指定索引位置的枚举值当ENUM类型的字段没有声明为NOT NULL时插入NULL也是有效的

CREATE TABLE test_enum(
season ENUM('春','夏','秋','冬','unknow')
);

INSERT INTO test_enum
VALUES('UNKNOW');     -- success
VALUES('1'),( 3 );    -- success,等同于:VALUES('春'),('秋');
VALUES('ab');         -- fail,不存在
VALUES(NULL);         -- success

SET类型

成员个数范围(L表示实际成员个数) 占用的存储空间
1 <= L <= 8 1 个字节
9 <= L <= 16 2 个字节
17 <= L <= 24 3 个字节
25 <= L <= 32 4 个字节
33 <= L <= 64 8 个字节

设置字段值时,可以取取值范围内的 0 个或多个值。

插入数据时:插入重复的SET类型成员时会自动删除重复的成员向SET类型的字段插入SET成员中不存在的值时会报错

二进制字符串类型

BINARY与VARBINARY

二进制字符串类型 特点 值的长度 占用空间
BINARY(M) 固定长度 M( 0 <= M <= 255 ) M个字节
VARBINARY(M) 可变长度 M( 0 <= M <= 65535 ) M+ 1 个字节
  • BINARY类型如果未指定(M),表示只能存储 1 个字节。如果字段值不足(M)个字节,将在右边填充’\ 0 ‘以补齐指定长度。
  • VARBINARY类型的数据除了存储数据本身外,还需要 1 或 2 个字节来存储数据的字节数。VARBINARY类型必须指定(M),否则报错。

BLOB

二进制字符串类型 值的长度 长度范围 占用空间
TINYBLOB L 0 <= L <= 255 L + 1 个字节
BLOB L 0 <= L <= 65535(相当于64KB) L + 2 个字节
MEDIUMBLOB L 0 <= L <= 16777215 (相当于16MB) L + 3 个字节
LONGBLOB L 0 <= L <= 4294967295(相当于4GB) L + 4 个字节

在实际工作中,往往不会在MySQL数据库中使用BLOB类型存储大对象数据,通常会将图片、音频和视频文件存储到服务器的磁盘上,并将图片、音频和视频的访问路径存储到MySQL中。

TEXT和BLOB的使用注意事项:

  1. BLOB和TEXT值也会引起自己的一些问题,特别是执行了大量的删除或更新操作的时候。删除这种值会在数据表中留下很大的”空洞“,以后填入这些”空洞”的记录可能长度不同。为了提高性能,建议定期使用 OPTIMIZE TABLE 功能对这类表进行碎片整理
  2. 如果需要对大文本字段进行模糊查询,MySQL 提供了前缀索引。但是仍然要在不必要的时候避免检索大型的BLOB或TEXT值。例如,SELECT * 查询就不是很好的想法,除非你能够确定作为约束条件的WHERE子句只会找到所需要的数据行。否则,你可能毫无目的地在网络上传输大量的值。
  3. 把BLOB或TEXT列分离到单独的表中。在某些环境中,如果把这些数据列移动到第二张数据表中,可以让你把原数据表中的数据列转换为固定长度的数据行格式,那么它就是有意义的。这会减少主表中的碎片,使你得到固定长度数据行的性能优势。它还使你在主数据表上运行 SELECT * 查询的时候不会通过网络传输大量的BLOB或TEXT值。

位类型:BIT

BIT类型中存储的是二进制值,类似 010110 。

二进制字符串类型 长度 长度范围 占用空间
BIT(M) M 1 <= M <= 64 约为(M + 7 )/ 8 个字节

BIT类型,如果没有指定(M),默认是 1 位。这个 1 位,表示只能存 1 位的二进制值。这里(M)是表示二进制的位数,位数最小值为 1 ,最大值为 64 。

使用SELECT命令查询位字段时,可以用BIN()HEX()函数进行转二进制和十六进制数读取。使用b+ 0 查询数据时,也可以直接查询出存储的十进制数据的值。

SELECT BIN(column2),HEX(column2) FROM test_bit1;
SELECT column2 + 0 FROM test_bit1;

标签:存储,字节,数据类型,00,类型,MySQL,------,长度
From: https://www.cnblogs.com/bairentianshi/p/17080116.html

相关文章

  • SpringBoot 整合 JDBC 实例
     0、数据库表CREATEDATABASEspringboot;USEspringboot;CREATETABLE`user`(`id`int(11)NOTNULLAUTO_INCREMENTCOMMENT'主键',`name`varchar(50)D......
  • Dubbo 中 Zookeeper 注册中心原理分析
    Dubbo中Zookeeper注册中心原理分析https://mp.weixin.qq.com/s/XbLxxmqoxVkYS_eDM4cauA本文通过分析Dubbo中ZooKeeper注册中心的实现ZooKeeperResitry的继承体系结构,......
  • vivo 故障定位平台的探索与实践
    vivo故障定位平台的探索与实践https://mp.weixin.qq.com/s?__biz=MzI4NjY4MTU5Nw==&mid=2247495930&idx=2&sn=8830003fac4710e1daceb76d766849f1&chksm=ebdb8068dcac097e......
  • 基础知识-语言进化史
    C语言——1972年诞生优势:贴近硬件,效率高劣势:指针和内存管理(运行暴露bug,浪费大量时间调试)非可移植性C+++——1982年诞生优势:面向对象,性能较好,兼容C劣势:特性复杂Java—......
  • 1154
    #include<iostream>usingnamespacestd;intyinzizhihe(inta){intb=0;for(inti=1;i<a;i++){if(a%i==0){b=b+i;}......
  • 百度离线地图地点搜索 离线地图poi搜索
    1.场景和需求:在局域网开发的web项目,不能连接公网1需要使用离线地图展示设备点位;2需要实现地图的城市范围内的离线搜索,可以检索到百度地图上的点位,类似与百度地图首......
  • 68、缓存---缓存使用---解决缓存穿透、雪崩
    1、空结果缓存:解决缓存穿透*2、设置过期时间(加随机值):解决缓存雪崩从上面逻辑可以看出,当redis中为空时,我们查询数据库,不论有没有查到结果,都进行缓存,解决了缓存穿透......
  • C语言#初识C语言(一)
    自学C语言的第1天。1、什么是C语言2、第一个C程序3、数据类型和格式字符4、变量、常量1、什么是C语言 C语言是一种高级语言,在1972年由丹尼斯·里奇和肯·汤姆逊在开发UNIX......
  • 接口测试|postman发送POST请求
    Postman发送POST请求postman发送POST请求示例:微信公众平台创建用户标签接口,业务操作如下:1、打开微信公众平台,微信扫码登录:​​https://mp.weixin.qq.com/debug/cgi-bin/sand......
  • 有关类型判断的总结
    1.判断是否为(String)类型isString=o=>Object.prototype.toString.call(o)==='[objectString]'2.判断是否为(Number)类型isNumber=o=>Object.prototype.toString.cal......