本教程以MySQL8为主版本(内容兼顾MySQL5.7)。
所有MySQL文章的目录为:总目录 https://blog.csdn.net/zyplanke/article/details/102968014
参照官方文档,梳理总结了常用的MySQL的数据类型。包括字符类型、数值类型、日间时间类型。
一个大坑:在where条件中字符和数字可以直接用等号,且结果正确。比如字段ColA类型为字符串,标准SQL写法:where ColA ='123',非标准写法为where ColA =123,也能获得正确的结果。 但是可能引起严重的性能问题和锁等待问题,因为在MySQL内部执行计划是不同的:标准SQL写法有索引则会使用索引直接获得结果;但非标准写法,无法匹配使用索引,先全表扫描然后从结果集中最后过滤筛选(最后筛选时才匹配上)。 同因此原因,在InnoDB下,非标准写法因全表扫描导致全部行都锁定,效果等同于表锁,可能引发严重的锁冲突和等待。
字符类型
Type | 定义 | 注意 |
CHAR(N) | 可存放固定N个字符, N最大值为255 | 值不够长时,自动右补空格存储。 值超长,自动去除尾部字符。 |
VARCHAR(N) | 可存放最多N个字符, N最大值为65535 | |
BINARY | 二进制字符串 | |
VARBINARY | 二进制字符串 | |
BLOB | 二进制大对象,可以容纳可变数量的数据 | 一般存放图片,音频等二进制数据 |
TEXT | 字符类大对象 | 一般存放文本等字符数据 |
ENUM | (单选)枚举类型。 | |
SET | (多选)集合枚举类型 |
- 关于字符串长度单位是字节还是字符的说明:
在字符集为utf8的情况下(对于MySQL5.7,需要将MySQL server端和connect等字符集设置为utf8mb4),字符串类型长度定义的单位是字符,不是字节。 length函数计算的是字节数,char_length函数计算的是字符数。验证如下:
mysql> create table TB (colA char(13), colB varchar(13));
Query OK, 0 rows affected (0.00 sec)
mysql> insert into TB values ('中华人民共和国地图abc中国', '中华人民共和国地图abc中国');
ERROR 1406 (22001): Data too long for column 'colA' at row 1
mysql> insert into TB values ('中华人民共和国地图abc中', '中华人民共和国地图abc中国');
ERROR 1406 (22001): Data too long for column 'colB' at row 1
mysql> insert into TB values ('中华人民共和国地图abc中', '中华人民共和国地图abc中');
Query OK, 1 row affected (0.00 sec)
mysql> select length(colA), char_length(colA), length(colB), char_length(colB) from TB;
+--------------+-------------------+--------------+-------------------+
| length(colA) | char_length(colA) | length(colB) | char_length(colB) |
+--------------+-------------------+--------------+-------------------+
| 33 | 13 | 33 | 13 |
+--------------+-------------------+--------------+-------------------+
1 row in set (0.00 sec)
- 关于字段尾部空格的处理
对于CHAR类型,MySQL在检索时会自动把值的尾部空格删除:
mysql> CREATE TABLE vc (v VARCHAR(4), c CHAR(4));
Query OK, 0 rows affected (0.01 sec)
mysql> INSERT INTO vc VALUES ('ab ', 'ab ');
Query OK, 1 row affected (0.00 sec)
mysql> SELECT CONCAT('(', v, ')'), CONCAT('(', c, ')') FROM vc;
+---------------------+---------------------+
| CONCAT('(', v, ')') | CONCAT('(', c, ')') |
+---------------------+---------------------+
| (ab ) | (ab) |
+---------------------+---------------------+
1 row in set (0.06 sec)
mysql> SELECT LENGTH(v), LENGTH(c) FROM vc;
+-----------+-----------+
| LENGTH(v) | LENGTH(c) |
+-----------+-----------+
| 4 | 2 |
+-----------+-----------+
1 row in set (0.00 sec)
因为在MySQL中所有字符类型都是PAD SPACE类型。这意味着 在所有 CHAR,VARCHAR和 TEXT类型的值进行比较时,都会按统一的PAD处理,可以不考虑尾部空格情况。 但是Like判断除外:
mysql> CREATE TABLE names (myname CHAR(10));
Query OK, 0 rows affected (0.01 sec)
mysql> INSERT INTO names VALUES ('Jones');
Query OK, 1 row affected (0.00 sec)
mysql> SELECT myname = 'Jones', myname = 'Jones ' FROM names;
+------------------+--------------------+
| myname = 'Jones' | myname = 'Jones ' |
+------------------+--------------------+
| 1 | 1 |
+------------------+--------------------+
1 row in set (0.00 sec)
mysql> SELECT myname LIKE 'Jones', myname LIKE 'Jones ' FROM names;
+---------------------+-----------------------+
| myname LIKE 'Jones' | myname LIKE 'Jones ' |
+---------------------+-----------------------+
| 1 | 0 |
+---------------------+-----------------------+
1 row in set (0.00 sec)
数值类型
分类 | Type | 字节 | 值范围 | 备注 |
整数 | TINYINT | 1 | 有符号数:-128 to 127 无符号数:0 to 255 | 默认是有符号 |
SMALLINT | 2 | 有符号数:-32768 to 32767 无符号数:0 to 65535 | 默认是有符号 | |
MEDIUMINT | 3 | 有符号数:-8388608 to 8388607 无符号数:0 to 16777215 | 默认是有符号 | |
INT、INTEGER | 4 | 有符号数:-2147483648 to 2147483647 无符号数:0 to 4294967295 | 默认是有符号 | |
BIGINT | 8 | 有符号数:-9223372036854775808 to 9223372036854775807 无符号数:0 to 18446744073709551615 | 默认是有符号 | |
浮点 | FLOAT | 4 | -3.402823466E+38 to -1.175494351E-38, 0 以及 1.175494351E-38 to 3.402823466E+38 | |
DOUBLE | 8 | -1.7976931348623157E+308 to -2.2250738585072014E-308, 以及2.2250738585072014E-308 to 1.7976931348623157E+308 | ||
DEC(M,D)、DECIMAL(M,D) | M+2 | M是数字总位数(包括小数位),D是小数位数 | ||
位 | BIT(M) | 1~8 | 最小值:BIT(1),最大值:BIT(64) |
(从MySQL 8.0.17起,zerofill已经废弃)。对于整数类型,还可以与zerofill一起指定显示宽度(display width),不影响实际存储。在type名词后用小括号设置显示宽度(display width)。zerofill就是用“0”填充,就是在数字位数不够时,显示时自动在前面用“0”填满至指定宽度。例如:
mysql> create table tb1( col1 int , col2 int(6), col3 int(6) zerofill );
Query OK, 0 rows affected (0.01 sec)
mysql> insert into tb1 values ( 11, 11, 11);
Query OK, 1 row affected (0.00 sec)
mysql> select * from tb1;
+------+------+--------+
| col1 | col2 | col3 |
+------+------+--------+
| 11 | 11 | 000011 |
+------+------+--------+
1 row in set (0.00 sec)
mysql> insert into tb1 values ( 222222222, 222222222, 222222222);
Query OK, 1 row affected (0.00 sec)
mysql> select * from tb1;
+-----------+-----------+-----------+
| col1 | col2 | col3 |
+-----------+-----------+-----------+
| 11 | 11 | 000011 |
| 222222222 | 222222222 | 222222222 |
+-----------+-----------+-----------+
2 rows in set (0.00 sec)
日间时间类型
Type | 定义 | 注意 |
DATE | 存放年月日没有时间。范围'1000-01-01' to '9999-12-31'。 | |
DATETIME | 存放年月日以及时间。范围'1000-01-01 00:00:00' to '9999-12-31 23:59:59'。精度:六位微妙 | |
TIMESTAMP | 存放年月日以及时间。范围UTC'1970-01-01 00:00:01' to '2038-01-19 03:14:07'。精度:六位微妙 | |
TIME | 时分秒。范围 '-838:59:59'到 '838:59:59'。小时范围很大,因为该类型仅可以用来表示一天中的某个时间,还可表示两个事件之间的时间间隔 | |
YEAR | YEAR类型是1字节类型,用于表示年份值。范围 1901为2155,和 0000 |
为日期时间类型的字段自动赋值
对于TIMESTAMP或DATETIME类型的字段,有两个自动赋值的属性:DEFAULT CURRENT_TIMESTAMP 和 ON UPDATE CURRENT_TIMESTAMP。
- DEFAULT CURRENT_TIMESTAMP 在insert新增一条记录时,如果insert中没有赋值,则自动将当前时间作为该字段的值。一般用于存放数据创建时间(create_time)。
- ON UPDATE CURRENT_TIMESTAMP 在update更新一条记录时,当该数据的其他字段发生变化时,此字段值也自动更新为最新的当前时间,一般用于存放数据的更改时间(change_time)。
测试验证如下:
mysql> CREATE TABLE tt (
colA DATETIME,
colB DATETIME DEFAULT CURRENT_TIMESTAMP,
colC DATETIME ON UPDATE CURRENT_TIMESTAMP,
colD DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
Query OK, 0 rows affected (0.00 sec)
mysql> insert into tt values ('2001-01-01 01:01:01', '2001-01-01 01:01:01', '2001-01-01 01:01:01', '2001-01-01 01:01:01');
Query OK, 1 row affected (0.00 sec)
mysql> select * from tt;
+---------------------+---------------------+---------------------+---------------------+
| colA | colB | colC | colD |
+---------------------+---------------------+---------------------+---------------------+
| 2001-01-01 01:01:01 | 2001-01-01 01:01:01 | 2001-01-01 01:01:01 | 2001-01-01 01:01:01 |
+---------------------+---------------------+---------------------+---------------------+
1 row in set (0.00 sec)
mysql> insert into tt (colA) values ('2002-02-02 02:02:02');
Query OK, 1 row affected (0.00 sec)
mysql> select * from tt;
+---------------------+---------------------+---------------------+---------------------+
| colA | colB | colC | colD |
+---------------------+---------------------+---------------------+---------------------+
| 2001-01-01 01:01:01 | 2001-01-01 01:01:01 | 2001-01-01 01:01:01 | 2001-01-01 01:01:01 |
| 2002-02-02 02:02:02 | 2019-11-06 22:40:08 | NULL | 2019-11-06 22:40:08 |
+---------------------+---------------------+---------------------+---------------------+
2 rows in set (0.00 sec)
mysql> update tt set colA='2003-03-03 03:03:03' where colA='2002-02-02 02:02:02';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from tt;
+---------------------+---------------------+---------------------+---------------------+
| colA | colB | colC | colD |
+---------------------+---------------------+---------------------+---------------------+
| 2001-01-01 01:01:01 | 2001-01-01 01:01:01 | 2001-01-01 01:01:01 | 2001-01-01 01:01:01 |
| 2003-03-03 03:03:03 | 2019-11-06 22:40:08 | 2019-11-06 22:41:44 | 2019-11-06 22:41:44 |
+---------------------+---------------------+---------------------+---------------------+
2 rows in set (0.00 sec)
JSON类型
包含若干个元素的JSON数组,用逗号分隔,两边中括号。格式为:
["abc", 10, null, true, false]
包含Key:Value形式的多个元素,用逗号分隔,两边花括号。格式为:
{"k1": "value", "k2": 10}
嵌套形式:
[99, {"id": "HK500", "cost": 75.99}, ["hot", "cold"]]
{"k1": "value", "k2": [10, 20]}
以上是基础知识。 下面演示JSON在MySQLMySQL中的用法:
mysql> CREATE TABLE t1 (jdoc JSON);
ERROR 1050 (42S01): Table 't1' already exists
mysql> CREATE TABLE tt (jdoc JSON);
Query OK, 0 rows affected (0.01 sec)
mysql> INSERT INTO tt VALUES('{"key1": "value1", "key2": "value2"}');
Query OK, 1 row affected (0.00 sec)
#插入一个不满足JSON格式要求的数据
mysql> INSERT INTO t1 VALUES('[1, 2,');
ERROR 1366 (HY000): Incorrect integer value: '[1, 2,' for column 'i' at row 1
还有很多JSON相关操作,见官方文档:https://dev.mysql.com/doc/refman/8.0/en/json.html
Spatial空间数据类型
需要先理解空间涉及的概念。见官方文档https://dev.mysql.com/doc/refman/8.0/en/spatial-types.html