mysql(一)数据类型

文章详细介绍了MySQL中的数据类型,包括整数类型(tinyint,smallint,mediumint,int,bigint)及其选择策略,浮点数类型(float,double)的精度问题,定点数类型(decimal)的精准性,以及字符串类型(char,varchar)的应用场景。强调了在精度要求高的场景中应使用定点数类型,而在存储范围大且对精度要求不高的情况下,可以选择浮点数类型。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

mysql的数据类型细分下来大致有以下几种

  • 整数类型:tinyint,smallint,mediumint,int,bigint
  • 浮点数类型:float,double
  • 定点数类型:decimal
  • 字符串类型:char,varchar
  • 日期时间类型:date,time,datetime,timestamp,year
  • 文本类型: tinytext ,text ,mediumtext , longtext
  • 枚举类型: enum
  • 集合类型: set
  • 二进制字符串类型:binary,varbinary,tinyblob,blob,mediumblob ,longblob
  • JSON类型:JSON对象,JSON数组
  • 空间数据类型:…

1.整数类型:tinyint,smallint,mediumint,int,bigint

类型大小范围(有符号,默认)范围(无符号)使用场景对应java类
tinyint1Bytes(-128,127)(0,255)一般用于枚举数据,比如系统设定取值范围很小且固定的场景Integer
samllint2Bytes(-32 768,32 767)(0,65 535)可以用于较小范围的统计数据,比如统计工厂的固定资产库存数量等Integer
mediumint3Bytes(-8 388 608,8 388 607)(0,16 777 215)用于较大整数的计算,比如车站每日的客流量等Integer
int4Bytes(-2 147 483 648,2 147 483 647)(0,4 294 967 295)取值范围足够大,一般情况下不用考虑超限问题,用得最多。比如商品编号,idInteger
bigint8Bytes(-9,223,372,036,854,775,808,9 223 372 036 854 775 807)(0,18 446 744 073 709 551 615)只有当你处理特别巨大的整数时才会用到。比如双十一的交易量、大型门户网站点击量、证券公司衍生产品持仓等Long

1.1,如何选择整数类型

在评估用哪种整数类型的时候,你需要考虑 存储空间 和 可靠性 的平衡问题:一方 面,用占用字节数少的整数类型可以节省存储空间;另一方面,要是为了节省存储空间, 使用的整数类型取值范围太小,一旦遇到超出取值范围的情况,就可能引起 系统错误 ,影响可靠性。举个例子,商品编号采用的数据类型是 INT。原因就在于,客户门店中流通的商品种类较多,而且,每天都有旧商品下架,新商品上架,这样不断迭代,日积月累。如果使用 SMALLINT 类型,虽然占用字节数比 INT 类型的整数少,但是却不能保证数据不会超出范围65535。相反,使用 INT,就能确保有足够大的取值范围,不用担心数据超出范围影响可靠性的问题。你要注意的是,在实际工作中,系统故障产生的成本远远超过增加几个字段存储空间所产生的成本。因此,我建议你首先确保数据不会超过取值范围,在这个前提之下,再去考虑如何节省存储空间,看似节省空间不多,但是当数据达到百万,千万以上时,节省下来的空间还是很客观的

在声明整数类型列时,例如 int(n) ,但实际上这里的 n 跟存储没有什么关系,无论 n 是什么,int 数据类型都是 4 个字节,只能存储 -2 147 483 648~2 147 483 647(有符号时)范围的数据。在mysql手册中这个 n 表示最大显示宽度,显示宽度与存储大小和数据类型所能包含的值的范围无关,最大有效的显示宽度是255,即 n 的值最大是 255。

比如我声明一个字段为 number int(5) ,此时该 number 字段也是占 4 个字节,也只能存储 -2 147 483 648~2 147 483 647(有符号时)范围的数据。

这个 n 的作用只有在我们给列加上 ZEROFILL(用 0 填充)属性时才会体现出来,并且只有在使用一些特定的客户端输出时才会有体现。比如:`

number` int(5) unsigned zerofill       -- 加上zerofill属性则必须同时加unsigned属性

此时,当该列某条数据的数字小于 5 位时,在某些特定的客户端检索输出时,会在数字前 “补0”,凑足5位数字。例如存储的数字是123,那么输出00123 。如果大于 5 位则原样显示原数字。

注意,不是在数据库中存储时会自动补 0 ,而是在某一些客户端查询输出时才有显示效果,目前仅发现使用在MySQL Shell才有显示效果,其他客户端连接时均无。所以说,基本没有开发者会使用这个特性,因为基本没什么用。

2.浮点数类型:float,double

类型大小范围(有符号,默认)范围(无符号)使用场景对应java类
float4Bytes(-3.402 823 466 E+38,-1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38)0,(1.175 494 351 E-38,3.402 823 466 E+38)单精度,浮点数值。学生成绩、允许有误差的、单精度浮点数Float
double8Bytes(-1.797 693 134 862 315 7 E+308,-2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308)0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308)双精度,浮点数值。学生成绩、允许有误差的、双精度浮点数Double

2.1精度说明

对于浮点类型,在MySQL中单精度值使用 4 个字节,双精度值使用 8 个字节。

  • MySQL允许使用 非标准语法 (其他数据库未必支持,因此如果涉及到数据迁移,则最好不要这么用): FLOAT(M,D) 或 DOUBLE(M,D) 。这里,M称为 精度 ,D称为 标度 。(M,D)中 M=整数位+小数位,D=小数位。 D<=M<=255,0<=D<=30。

    例如,定义为FLOAT(5,2)的一个列可以显示为-999.99-999.99。如果超过这个范围会报错。

  • FLOAT和DOUBLE类型在不指定(M,D)时,默认会按照实际的精度(由实际的硬件和操作系统决定)来显示

  • 说明:浮点类型,也可以加 UNSIGNED ,但是不会改变数据范围,例如:FLOAT(3,2) UNSIGNED仍然只能表示0-9.99的范围。

  • 不管是否显式设置了精度(M,D),这里MySQL的处理方案如下:
    。 如果存储时,整数部分超出了范围,MySQL就会报错,不允许存这样的值
    。如果存储时,小数点部分若超出范围,就分以下情况:若四舍五入后,整数部分没有超出范围,则只警告,但能成功操作并四舍五入删除多余的小数位后保存。例如在FLOAT(5,2)列内插 入999.009,近似结果是999.01。若四舍五入后,整数部分超出范围,则MySQL报错,并拒绝处理。如FLOAT(5,2)列内插入999.995和-999.995都会报错。

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

  • CREATE TABLE test_double1( f1 FLOAT, f2 FLOAT(5,2), f3 DOUBLE, f4 DOUBLE(5,2) ); DESC test_double1; INSERT INTO test_double1 VALUES(123.456,123.456,123.4567,123.45); #Out of range value for column 'f2' at row 1 INSERT INTO test_double1 VALUES(123.456,1234.456,123.4567,123.45); SELECT * FROM test_double1;

2.2精度误差说明

浮点数类型有个缺陷,就是不精准。下面我来重点解释一下为什么 MySQL 的浮点数不够精准。比如,我们设计一个表,有f1这个字段,插入值分别为0.47,0.44,0.19,我们期待的运行结果是:0.47 + 0.44 + 0.19 = 1.1。而使用sum之后查询:

CREATE TABLE test_double2(
f1 DOUBLE 
);
INSERT INTO test_double2 VALUES(0.47),(0.44),(0.19);

查询结果是 1.0999999999999999。看到了吗?虽然误差很小,但确实有误差。 你也可以尝试把数据类型改成 FLOAT,然后运行求和查询,得到的是, 1.0999999940395355。显然,误差更大了。

那么,为什么会存在这样的误差呢?问题还是出在 MySQL 对浮点类型数据的存储方式上。

MySQL 用 4 个字节存储 FLOAT 类型数据,用 8 个字节来存储 DOUBLE 类型数据。无论哪个,都是采用二进制的方式来进行存储的。比如 9.625,用二进制来表达,就是 1001.101,或者表达成 1.001101×2^3。如果尾数不是 0 或 5(比如 9.624),你就无法用一个二进制数来精确表达。进而,就只好在取值允许的范围内进行四舍五入。

在编程中,如果用到浮点数,要特别注意误差问题,因为浮点数是不准确的,所以我们要避免使用“=”来**判断两个数是否相等。**同时,在一些对精确度要求较高的项目中,千万不要使用浮点数,不然会导致结果错误,甚至是造成不可挽回的损失。那么,MySQL 有没有精准的数据类型呢?当然有,这就是定点数类型: DECIMAL 。

3.定点数类型:decimal

先说 浮点数,float 和 double 都代表浮点数,区别简单记就是 float 默认占 4 Byte。

float ( p) 中的 p 代表整数位最小精度。如果 p > 24 则直接转换为 double,占 8 Byte。p 最大值为 53,但最大值存在计算不精确的问题。
再说 定点数,包括 decimal 以及同义词 numeric,定点数的整数位和小数位分别存储,有效精度最大不能超过 65。
所以区别于 float 的在于精确存储,必须需要精确存储或者精确计算的最好定义为 decimal 即可。

  • 使用 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决定的。DECIMAL 的存储空间并不是固定的,由精度值M决定,总共占用的存储空间为M+2个字节。也就是说,在一些对精度要求不高的场景下,比起占用同样字节长度的定点数,浮点数表达的数值范围可以更大一些。
  • 定点数在MySQL内部是以 字符串 的形式进行存储,这就决定了它一定是精准的。
  • 当DECIMAL类型不指定精度和标度时,其默认为DECIMAL(10,0)。当数据的精度超出了定点数类型的精度范围时,则MySQL同样会进行四舍五入处理。
  • 浮点数相对于定点数的优点是在长度一定的情况下,浮点类型取值范围大,但是不精准,适用于需要取值范围大,又可以容忍微小误差的科学计算场景(比如计算化学、分子建模、流体动力学等)
  • 定点数类型取值范围相对小,但是精准,没有误差,适合于对精度要求极高的场景 (比如涉及金额计算的场景)

示例 3
创建一张表 y1,分别给字段 f1,f2,f3 不同的类型。

mysql-(ytt/3305)->create table y1(f1 float,f2 double,f3 decimal(10,2));

Query OK, 0 rows affected (0.03 sec)

插入一些数值。

mysql-(ytt/3305)->insert into y1 values (10.2,10.2,10.2);

Query OK, 1 row affected (0.01 sec)



mysql-(ytt/3305)->insert into y1 values (100.12,100.12,100.12);

Query OK, 1 row affected (0.01 sec)



mysql-(ytt/3305)->insert into y1 values (1001.12,1001.12,1001.12);

Query OK, 1 row affected (0.01 sec)



mysql-(ytt/3305)->insert into y1 values (12001.12,12001.12,12001.12);

Query OK, 1 row affected (0.01 sec)



mysql-(ytt/3305)->insert into y1 values (12001222.12,12001222.12,12001222.12);

Query OK, 1 row affected (0.00 sec)

检索记录数,发现 f1 里面存放的记录数已经不准确了。

mysql-(ytt/3305)->select * from y1;

+---------+----------+----------+

| f1      | f2       | f3       |

+---------+----------+----------+

|    10.2 |     10.2 |    10.20 |

|  100.12 |   100.12 |   100.12 |

| 1001.12 |  1001.12 |  1001.12 |

| 12001.1 | 12001.12 | 12001.12 |

+---------+----------+----------+

4 rows in set (0.00 sec)

那把 f3 的精度改大点,看看 double 的存储。

mysql-(ytt/3305)->alter table y1 modify f3 decimal(50,10);

Query OK, 5 rows affected (0.06 sec)

Records: 5  Duplicates: 0  Warnings: 0

插入一条更大的记录。
mysql-(ytt/3305)->insert into y1 values (123456789010.1234567,123456789010.1234567,123456789010.1234567);

Query OK, 1 row affected (0.01 sec)

检索发现只有 f3 的值是精确的。

mysql-(ytt/3305)->select * from y1;

+--------------+--------------------+-------------------------+

| f1           | f2                 | f3                      |

+--------------+--------------------+-------------------------+

|         10.2 |               10.2 |           10.2000000000 |

|       100.12 |             100.12 |          100.1200000000 |

|      1001.12 |            1001.12 |         1001.1200000000 |

|      12001.1 |           12001.12 |        12001.1200000000 |

|     12001200 |        12001222.12 |     12001222.1200000000 |

| 123457000000 | 123456789010.12346 | 123456789010.1234567000 |

+--------------+--------------------+-------------------------+

6 rows in set (0.00 sec)

“由于 DECIMAL 数据类型的精准性,在我们的项目中,除了极少数(比如商品编号)用到整数类型外,其他的数值都用的是
DECIMAL,原因就是这个项目所处的零售行业,要求精准,一分钱也不能差。 ” ——来自某项目经理

4.字符串类型:char,varchar

字符类型和整形一样,用途也很广。用来存储字符、字符串、MySQL 所有未知的类型。可以简单说是万能类型!

类型大小用途
char0-255 bytes(字节)定长字符串
varchar0-65535 bytes变长字符串
  • char(10) 代表最大支持 10 个字符存储,varchar(10) 虽然和 char(10) 可存储的字符数一样多,不同的是 varchar 类型存储的是实际大小,char 存储的理论固定大小。具体的字节数和字符集相关。

  • 常用的字符串类型的数据类型有 CHAR 和 VARCHAR 两种,两者后面都必须要跟上一个数字表示长度,例如 CHAR(10)、VARCHAR(10)

  • char(n) 和 varchar(n) 括号中的 n 代表最大可容纳的字符的个数,并不代表字节个数。注意,一个中文和一个英文都是 1 个字符,只不过 mysql 的编码格式不同时,1 个中文和 1 个英文所占用的存储字节不同而已。(虽然在早期的版本中,n 指的是字节数,但已经是非常旧的版本了,估计一般人也用不到)

  • CHAR(n) 和 VARCHAR(n) 都是表示可存储 n 个字符,但是 char 类型在少于 n 个字符时,会在字符串的右边使用空格来填充以达到 n 个字符。
    比如:CHAR(4) 和 VARCHAR(4) ,对于 CHAR(4) 表示固定容纳4个字符,当少于4个字符时,会使用空格填充空缺的部分,如果超过4个字符,会自动截断超出部分。例如你存入数据为 ‘ab’ ,实际会存入 'ab ’ (ab后有2个空格)。但是如果我们使用 select 语句来查询 char 类型的字段时,会发现根本就没有自动补空格,这是因为 CHAR 字段在检索输出时,会自动省略右侧的空格。

  • VARCHAR 是 CHAR 类型的一个变体,它是一种可变长度的字符串类型,并且在声明时也必须要指定字符长度。VARCHAR 类型对于未达到 n 字符的情况不会补空。

  • CHAR 和 VARCHGAR 不同之处在于 MYSQL 数据库处理这个指示器(即 n)的方式:CHAR 把这个大小视为值的大小,在长度不足的情况下就用空格补足。而 VARCHAR 类型只会把 n 作为限制字符串的最大长度,短于指示器长度的 VARCHAR 类型不会被空格填补,但长于指示器的值仍然会被截短。

  • 关于计算 VARCHAR 类型字符串的占用空间,有一点需要说明的是, VARCHAR 类型字符串的占用空间实际上包含2部分,一是存储数据本身占用的空间,二是描述数据的元数据占用的空间,例如 VARCHAR 类型会使用1个字节记录存入数据实际的字符数。

    比如下面示例说明 varchar 字段的字符长度和占用存储字节数:

    (1) ‘a啊b’ —— 字符数为3,不补空,实际存入为 ‘a啊b’ ,字符数为3,字节数为 1+3+1=5 。

    (2)‘a啊b哈ccccccccc’ —— 字符数超出4,仅保留前4个字符,因此实际存入 ‘a啊b哈’ ,字符数:4,字节数:1+3+1+3=8 。这种情况和 CHAR 类型处理一致。

    (3)‘a啊和哈’ —— 字符数刚好为4,不需要截断和补齐,因此实际存入 ‘a啊和哈’ ,字符数:4,字节数:1+3+3+3=10

4.1使用场景:

  1. 存储很短的信息。比如门牌号码101,201……这样很短的信息应该用char,因为varchar还要占个byte用于存储信息长度,本来打算节约存储的,结果得不偿失。
  2. 固定长度的。比如使用uuid作为主键,那用char应该更合适。因为他固定长度,varchar动态根据长度的特性就消失了,而且还要占个长度信息。
  3. 十分频繁改变的column。因为varchar每次存储都要有额外的计算,得到长度等工作,如果一个非常频繁改变的,那就要有很多的精力用于计算,而这些对于char来说是不需要的。
  4. 具体存储引擎中的情况:
    。MyISAM 数据存储引擎和数据列:MyISAM数据表,最好使用固定长度(CHAR)的数据列代替可变长度(VARCHAR)的数据列。这样使得整个表静态化,从而使 数据检索更快 ,用空间换时间。
    。MEMORY 存储引擎和数据列:MEMORY数据表目前都使用固定长度的数据行存储,因此无论使用CHAR或VARCHAR列都没有关系,两者都是作为CHAR类型处理的。
    。InnoDB 存储引擎,建议使用VARCHAR类型。因为对于InnoDB数据表,内部的行存储格式并没有区分固定长度和可变长度列(所有数据行都使用指向数据列值的头指针),而且主要影响性能的因素 是数据行使用的存储总量,由于char平均占用的空间多于varchar,所以除了简短并且固定长度的,其他考虑varchar。这样节省空间,对磁盘I/O和数据存储总量比较好。

示例
例如下面表 t4 ,两个字段 c1,c2,分别为 char 和 varchar。

mysql-(ytt/3305)->create table t4 (c1 char(20),c2 varchar(20));

Query OK, 0 rows affected (0.02 sec)

插入一条记录。

mysql-(ytt/3305)->set @a = "我是傻傻的小月亮!!!!";

Query OK, 0 rows affected (0.00 sec)



mysql-(ytt/3305)->insert into t4 values (@a,@a);

Query OK, 1 row affected (0.00 sec)



mysql-(ytt/3305)->select * from t4;

+--------------------------------------+--------------------------------------+

| c1                                   | c2                                   |

+--------------------------------------+--------------------------------------+

| 我是傻傻的小月亮!!!!| 我是傻傻的小月亮!!!!|

+--------------------------------------+--------------------------------------+

1 row in set (0.00 sec)

分别拿出来两个字段的值,发现 c1 比 c2 多了很多内容,包括字符个数,字节数。

mysql-(ytt/3305)->SELECT 'c1' AS 'column list',

   -> char_length(c1) '  as characters',

   -> length(c1) ' as bytes'

   -> FROM t4

   -> UNION all

   -> SELECT 'c2',

   -> char_length(c2) as ' characters',

   -> length(c2) as ' bytes'

   -> FROM t4;

+-------------+---------------+----------+

| column list | as characters | as bytes |

+-------------+---------------+----------+

| c1          |            20 |       44 |

| c2          |            12 |       36 |

+-------------+---------------+----------+

2 rows in set, 4 warnings (0.00 sec)

5.日期时间类型:date,time,datetime,timestamp,year

类型大小( 固定长度、单位为字节)范围格式用途
date31000-01-01/9999-12-31YYYY-MM-DD(年月日)日期值
time3‘-838:59:59’/‘838:59:59’HH:MM:SS(时分秒)时间值或持续时间
datetime81000-01-01 00:00:00/9999-12-31 23:59:59YYYY-MM-DD HH:MM:SS(年月日时分秒)混合日期和时间值
timestamp41970-01-01 00:00:00/2038,结束时间是第 2147483647 秒,北京时间 2038-1-19 11:14:07,格林尼治时间 2038年1月19日 凌晨 03:14:07YYYYMMDD HHMMSS混合日期和时间值,时间戳
year11901/2155YYYY年份值

5.1 date类型

DATE类型表示日期,没有时间部分,格式为 YYYY-MM-DD ,其中,YYYY表示年份,MM表示月份,DD表示日期。需要 3个字节 的存储空间。在向DATE类型的字段插入数据时,同样需要满足一定的格式条件。

  • 以 YYYY-MM-DD 格式或者 YYYYMMDD 格式表示的字符串日期,其最小取值为1000-01-01,最大取值为9999-12-03。YYYYMMDD格式会被转化为YYYY-MM-DD格式。
  • 以 YY-MM-DD 格式或者 YYMMDD 格式表示的字符串日期,此格式中,年份为两位数值或字符串满足YEAR类型的格式条件为:当年份取值为00到69时,会被转化为2000到2069;当年份取值为70到99时,会被转化为1970到1999。
  • 使用 CURRENT_DATE() 或者 NOW() 函数,会插入当前系统的日期。

举例:
创建数据表,表中只包含一个DATE类型的字段f1。

CREATE TABLE test_date1(
	f1 DATE 
);
Query OK, 0 rows affected (0.13 sec)
#插入数据:
INSERT INTO test_date1 
VALUES ('2020-10-01'), ('20201001'),(20201001); 

INSERT INTO test_date1 
VALUES ('00-01-01'), ('000101'), ('69-10-01'), ('691001'), ('70-01-01'), ('700101'), ('99-01-01'), ('990101');

INSERT INTO test_date1 
VALUES (000301), (690301), (700301), (990301);

INSERT INTO test_date1 
VALUES (CURRENT_DATE()), (NOW()); 

SELECT * FROM test_date1;

5.2 time类型

TIME类型用来表示时间,不包含日期部分。在MySQL中,需要 3个字节 的存储空间来存储TIME类型的数据,可以使用“HH:MM:SS”格式来表示TIME类型,其中,HH表示小时,MM表示分钟,SS表示秒。

在MySQL中,向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。
  • 使用 CURRENT_TIME() 或者 NOW() ,会插入当前系统的时间。

举例:
创建数据表,表中包含一个TIME类型的字段f1。

CREATE TABLE test_time1(
	f1 TIME 
);
Query OK, 0 rows affected (0.02 sec) 
INSERT INTO test_time1 
VALUES('2 12:30:29'), ('12:35:29'), ('12:40'), ('2 12:40'),('1 05'), ('45'); 
INSERT INTO test_time1 
VALUES ('123520'), (124011),(1210); 
INSERT INTO test_time1 VALUES (NOW()), (CURRENT_TIME()); 
SELECT * FROM test_time1;

5.3 datetime

datetime类型在所有的日期时间类型中占用的存储空间最大,总共需要 8 个字节的存储空间。在格式上为date类型和time类型的组合,可以表示为 YYYY-MM-DD HH:MM:SS ,其中YYYY表示年份,MM表示月份,DD表示日期,HH表示小时,MM表示分钟,SS表示秒。在向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类型的字段插入系统的当前日期和时间。

举例:

#创建数据表,表中包含一个DATETIME类型的字段dt。
CREATE TABLE test_datetime1( 
    dt DATETIME 
);
Query OK, 0 rows affected (0.02 sec)
#插入数据:
INSERT INTO test_datetime1 
VALUES ('2021-01-01 06:50:30'), ('20210101065030'); 
INSERT INTO test_datetime1 
VALUES ('99-01-01 00:00:00'), ('990101000000'), ('20-01-01 00:00:00'), ('200101000000'); 
INSERT INTO test_datetime1 
VALUES (20200101000000), (200101000000), (19990101000000), (990101000000); 
INSERT INTO test_datetime1 VALUES (CURRENT_TIMESTAMP()), (NOW());

5.4 timestamp类型

TIMESTAMP类型也可以表示日期时间,其显示格式与DATETIME类型相同,都是 YYYY-MM-DD HH:MM:SS ,需要4个字节的存储空间。但是TIMESTAMP存储的时间范围比DATETIME要小很多,只能存储“1970-01-01 00:00:01 UTC”到“2038-01-19 03:14:07 UTC”之间的时间。其中,UTC表示世界统一时间,也叫作世界标准时间。

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

向TIMESTAMP类型的字段插入数据时,当插入的数据格式满足YY-MM-DD HH:MM:SS和YYMMDDHHMMSS时,两位数值的年份同样符合YEAR类型的规则条件,只不过表示的时间范围要小很多。如果向TIMESTAMP类型的字段插入的时间超出了TIMESTAMP类型的范围,则MySQL会抛出错误信息。

举例:

#创建数据表,表中包含一个TIMESTAMP类型的字段ts。
CREATE TABLE test_timestamp1( 
    ts TIMESTAMP 
);
#插入数据:
INSERT INTO test_timestamp1 
VALUES ('1999-01-01 03:04:50'), ('19990101030405'), ('99-01-01 03:04:05'), ('990101030405'); 
INSERT INTO test_timestamp1 
VALUES ('2020@01@01@00@00@00'), ('20@01@01@00@00@00'); 
INSERT INTO test_timestamp1 
VALUES (CURRENT_TIMESTAMP()), (NOW()); 
#Incorrect datetime value 
INSERT INTO test_timestamp1 VALUES ('2038-01-20 03:14:07');

TIMESTAMP和DATETIME的区别:

  • TIMESTAMP存储空间比较小,表示的日期时间范围也比较小
  • 底层存储方式不同,TIMESTAMP底层存储的是毫秒值,距离1970-1-1 0:0:0 0毫秒的毫秒值。
  • 两个日期比较大小或日期计算时,TIMESTAMP更方便、更快。
  • TIMESTAMP和时区有关。TIMESTAMP会根据用户的时区不同,显示不同的结果。而DATETIME则只能反映出插入时当地的时区,其他时区的人查看数据必然会有误差的。

5.5 year

YEAR类型用来表示年份,在所有的日期时间类型中所占用的存储空间最小,只需要 1个字节 的存储空间。在MySQL中,YEAR有以下几种存储格式:

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

从MySQL5.5.27开始,2位格式的YEAR已经不推荐使用。YEAR默认格式就是“YYYY”,没必要写成YEAR(4),

从MySQL 8.0.19开始,不推荐使用指定显示宽度的YEAR(4)数据类型。

CREATE TABLE test_year(
	f1 YEAR,
	f2 YEAR(4) 
);

注意:
timestamp 代表的时间戳是一个 int32 存储的整数,取值范围为 ‘1970-01-01 00:00:01.000000’ 到 ‘2038-01-19 03:14:07.999999’;
datetime 取值范围为 ‘1000-01-01 00:00:00.000000’ 到 ‘9999-12-31 23:59:59.999999’。
综上所述,日期这块类型的选择遵循以下原则:

  1. 如果时间有可能超过时间戳范围,优先选择 datetime。
  2. 如果需要单独获取年份值,比如按照年来分区,按照年来检索等,最好在表中添加一个 year 类型来参与。
  3. 如果需要单独获取日期或者时间,最好是单独存放,而不是简单的用 datetime 或者 timestamp。后面检索时,再加函数过滤,以免后期增加 SQL 编写带来额外消耗。
  4. 如果有保存毫秒类似的需求,最好是用时间类型自己的特性,不要直接用字符类型来代替。MySQL 内部的类型转换对资源额外的消耗也是需要考虑的。
  5. 用得最多的日期时间类型,就是 DATETIME 。虽然 MySQL 也支持 YEAR(年)、 TIME(时间)、DATE(日期),以及 TIMESTAMP 类型,但是在实际项目中,尽量用 DATETIME 类型。因为这个数据类型包括了完整的日期和时间信息,取值范围也最大,使用起来比较方便。毕竟,如果日期时间信息分散在好几个字段,很不容易记,而且查询的时候,SQL 语句也会更加复杂。此外,一般存注册时间、商品发布时间等,不建议使用DATETIME存储,而是使用 时间戳 ,因为DATETIME虽然直观,但不便于计算。

6.文本类型: tinytext ,text ,mediumtext , longtext

类型大小用途
tinytext0-255 bytes短文本字符串
text0-65 535 bytes长文本数据
mediumtext0-16 777 215 bytes中等长度文本数据
longtext0-4 294 967 295 bytes极大文本数据

注意:

TEXT文本类型,可以存比较大的文本段,搜索速度稍慢,因此如果不是特别大的内容,建议使用CHAR, VARCHAR来代替。还有TEXT类型不用加默认值,加了也没用。而且text和blob类型的数据删除后容易导致“空洞”,使得文件碎片比较多,所以频繁使用的表不建议包含TEXT类型字段,建议单独分出去,单独用一个表

7.枚举类型: enum

枚举类型,也即 enum。适合提前规划好了所有已经知道的值,且未来最好不要加新值的情形。枚举类型有以下特性:

  1. 最大占用 2 Byte。
  2. 最大支持 65535 个不同元素。
  3. MySQL 后台存储以下标的方式,也就是 tinyint 或者 smallint 的方式,下标从 1 开始。
  4. 排序时按照下标排序,而不是按照里面元素的数据类型。所以这点要格外注意。

示例
创建表 t7。

mysql-(ytt/3305)->create table t7(c1 enum('mysql','oracle','dble','postgresql','mongodb','redis','db2','sql server'));

Query OK, 0 rows affected (0.03 sec)

用下标插入数据。
mysql-(ytt/3305)->insert into t7 values (1);

Query OK, 1 row affected (0.40 sec)



mysql-(ytt/3305)->insert into t7 values (2);

Query OK, 1 row affected (0.00 sec)

用真实元素插入数据。
mysql-(ytt/3305)->insert into t7 values ('postgresql');

Query OK, 1 row affected (0.01 sec)



mysql-(ytt/3305)->insert into t7 values ('dble');

Query OK, 1 row affected (0.01 sec)



mysql-(ytt/3305)->insert into t7 values ('sql server');

查询结果出来,发现是按照之前定义的元素排序,也就是下标排序。

mysql-(ytt/3305)->select * from t7 order by c1;

+------------+

| c1         |

+------------+

| mysql      |

| oracle     |

| dble       |

| postgresql |

| sql server |

+------------+

5 rows in set (0.00 sec)

8.集合类型: set

集合类型 SET 和枚举类似,也是得提前知道有多少个元素。SET 有以下特点:

  1. 最大占用 8 Byte,int64。
  2. 内部以二进制位的方式存储,对应的下标如果以十进制来看,就分别为 1,2,4,8,…,pow(2,63)。
  3. 最大支持 64 个不同的元素,重复元素的插入,取出来直接去重。
  4. 元素之间可以组合插入,比如下标为 1 和 2 的可以一起插入,直接插入 3 即可。

示例
定义表 c7 字段 c1 为 set 类型,包含了 8 个值,也就是下表最大为 pow(2,7)。

mysql-(ytt/3305)->create table c7(c1 set('mysql','oracle','dble','postgresql','mongodb','redis','db2','sql server'));

Query OK, 0 rows affected (0.02 sec)

插入 1128 的所有组合。

mysql-(ytt/3305)->INSERT INTO c7

WITH RECURSIVE ytt_number (cnt) AS (

        SELECT 1 AS cnt

        UNION ALL

        SELECT cnt + 1

        FROM ytt_number

        WHERE cnt < pow(2, 7)

    )

SELECT *

FROM ytt_number;

Query OK, 128 rows affected (0.01 sec)

Records: 128  Duplicates: 0  Warnings: 0

查询的时候也是直接用下标或者元素来查。

mysql-(ytt/3305)->select * from c7 where c1 = 1;

+-------+

| c1    |

+-------+

| mysql |

+-------+

1 row in set (0.00 sec)



mysql-(ytt/3305)->select * from c7 where c1 = 'mysql';

+-------+

| c1    |

+-------+

| mysql |

+-------+

1 row in set (0.00 sec)

9.二进制字符串类型:binary,varbinary,tinyblob,blob,mediumblob ,longblob

MySQL中的二进制字符串类型主要存储一些二进制数据,比如可以存储图片、音频和视频等二进制数据

10.JSON类型

JSON(JavaScript Object Notation)是一种轻量级的 数据交换格式 。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。它易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。JSON 可以将 JavaScript 对象中表示的一组数据转换为字符串,然后就可以在网络或者程序之间轻 松地传递这个字符串,并在需要的时候将它还原为各编程语言所支持的数据格式。

在MySQL 5.7中,就已经支持JSON数据类型。在MySQL 8.x版本中,JSON类型提供了可以进行自动验证的JSON文档和优化的存储结构,使得在MySQL中存储和读取JSON类型的数据更加方便和高效

11.空间类型

MySQL 空间类型扩展支持地理特征的生成、存储和分析。这里的地理特征表示世界上具有位置的任何东西,可以是一个实体,例如一座山;可以是空间,例如一座办公楼;也可以是一个可定义的位置,例如一个十字路口等等。MySQL中使用 Geometry(几何) 来表示所有地理特征。Geometry指一个点或点的集合,代表世界上任何具有位置的事物。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值