整数类型
整数类型 | 字节 | 有符号数取值范围 | 无符号数取值范围 |
---|---|---|---|
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 |
可选属性:
-
UNSIGNED:无符号类型(非负)
-
ZEROFILL:0填充
-
(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的使用注意事项:
- BLOB和TEXT值也会引起自己的一些问题,特别是执行了大量的删除或更新操作的时候。删除这种值会在数据表中留下很大的”
空洞
“,以后填入这些”空洞”的记录可能长度不同。为了提高性能,建议定期使用OPTIMIZE TABLE
功能对这类表进行碎片整理
。 - 如果需要对大文本字段进行模糊查询,MySQL 提供了
前缀索引
。但是仍然要在不必要的时候避免检索大型的BLOB或TEXT值。例如,SELECT * 查询就不是很好的想法,除非你能够确定作为约束条件的WHERE子句只会找到所需要的数据行。否则,你可能毫无目的地在网络上传输大量的值。 - 把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