mysql的数据类型和字符集

时间:2021-10-20 15:13:46

MySQL的数据类型

MySQL数据库支持的数据类型主要有以下几种:

  • 整型
  • 浮点型
  • 字符
  • BLOB型
  • 枚举和集合类型
  • JSON类型(MySQL5.7新增加的支持)

整型

整数类型是数据库中最基本的数据类型。标准SQL中支持INTEGER和SMALLINT这两类整数类型。MySQL数据库除了支持这两种类型之外,还扩展支持了TINYINT, MEDIUMINT和BIGINT。

MySQL中各种整型占据的字节数和取值范文如下:

整数类型 字节数 无符号数取值范围 有符号数取值范围(添加一位符号为,把无符号数除以2) 默认显示宽度
TINYINT 1 0~2^8 -128~127 4
SMALLINT 2 0~2^16 -32768~32767 6
MEDIUMINT 3 0~2^24 -8388608~8388607 9
INT 4 0~2^32 -2147483648~2147483647 11
INTEGER 4 0~2^32 -2147483648~2147483647 11
BIGINT 8 0~2^64 -(2^64)/2~[(2^64)/2]  -1 20

INT类型和INTEGER类型的字节数和取值范围是一样,在MySQL中INT类型和INTEGER类型是一样的。

MySQL支持数据类型的名称后面指定该类型的显示宽度。

数据类型 (显示宽度)
#其中,数据类型参数是整数数据类型的名称,显示宽度参数是指定宽度的数值。
#在建表时,若是没有指定显示宽度,则MySQL使用默认的显示宽度:
mysql> create table tb3(a tinyint, b smallint, c mediumint, d int, e bigint);
Query OK, 0 rows affected (0.02 sec) mysql> show create table tb3; # 查看默认的显示宽度
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                                                        |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| tb3   | CREATE TABLE `tb3` (
  `a` tinyint(4) DEFAULT NULL,
  `b` smallint(6) DEFAULT NULL,
  `c` mediumint(9) DEFAULT NULL,
  `d` int(11) DEFAULT NULL,
  `e` bigint(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec) mysql>

整型的zerofill参数和auto_increment参数:

  • zerofill,在插入数据长度没有达到默认显示宽度时,用0填充。
mysql> create table tb4(a int() zerofill, b int());  # 建表时使用zerofill参数
Query OK, rows affected (0.01 sec) mysql> insert into tb4 values(,); #插入的数据不足时,用0填充。
Query OK, row affected (0.00 sec) mysql> select * from tb4;
+------+------+
| a | b |
+------+------+
| | |
+------+------+
row in set (0.00 sec) mysql> insert into tb4 values(10000,20000); #插入超过指定宽度的数据
Query OK, 1 row affected (0.00 sec) mysql> select * from tb4; #仍然会正常显示
+-------+-------+
| a     | b     |
+-------+-------+
|  0001 |     2 |
| 10000 | 20000 |
+-------+-------+
2 rows in set (0.00 sec) mysql> insert into tb4 values(123456789123,123456789123); #插入超过默认宽度的数据会报错
ERROR 1264 (22003): Out of range value for column 'a' at row 1
mysql>
  • auto_increment参数,自增长,需要注意的是自增长序列必须为索引,一张表中,只能有一个自增长的字段。
mysql> create table tb5(a int() auto_increment, b int);                     #直接创建会报错
ERROR (): Incorrect table definition; there can be only one auto column and it must be defined as a key
mysql> create table tb5(a int() auto_increment primary key, b int); #自增长列必须为索引
Query OK, rows affected (0.03 sec) mysql> insert into tb5(b) values(5); #插入字段b数值
Query OK, 1 row affected (0.00 sec) mysql> select * from tb5; #自增长列是从1开始的
+---+------+
| a | b    |
+---+------+
| 1 |    5 |
+---+------+
1 row in set (0.00 sec) #自增长列的下一个值,是从这个列中最大的一个数值+1,开始的,如下:
mysql> insert into tb5(b) values(8); #插入两条数据
Query OK, 1 row affected (0.01 sec) mysql> insert into tb5(b) values(9); #插入数据之后,字段a的值为3
Query OK, 1 row affected (0.00 sec) mysql> insert into tb5 values(-7, 21); #插入字段a的数值为-7
Query OK, 1 row affected (0.01 sec) mysql> insert into tb5(b) values(23); #再插入一条数据,字段a的值为4,而不是-6
Query OK, 1 row affected (0.00 sec) mysql> select * from tb5;
+----+------+
| a  | b    |
+----+------+
| -7 |   21 |
|  1 |    5 |
|  2 |    8 |
|  3 |    9 |
|  4 |   23 |
+----+------+
5 rows in set (0.00 sec) #可以设置自增长字段的初始值
mysql> create table tb5( a int(4) auto_increment primary key, b int) auto_increment=5; #设置初始值为5
Query OK, 0 rows affected (0.01 sec) mysql> insert into tb5(b) values(23);
Query OK, 1 row affected (0.01 sec) mysql> select * from tb5;
+---+------+
| a | b    |
+---+------+
| 5 |   23 |
+---+------+
1 row in set (0.00 sec) mysql> insert into tb5(b) values(21);
Query OK, 1 row affected (0.01 sec) mysql> select * from tb5;
+---+------+
| a | b    |
+---+------+
| 5 |   23 |
| 6 |   21 |
+---+------+
2 rows in set (0.00 sec)

浮点型

MySQL中使用浮点类型和定点数类型来表示小数。浮点数类型包括单精度浮点数和双精度浮点数。定点数类型就是DECIMAL型。

类型 字节数 负数取值范围 非负数取值范围
float 4 暂无 暂无
double 8 暂无 暂无
DECIMAL(M,D)或者DEC(M,D) M+2 暂无 暂无

MySQL可以指定浮点数和定点数的精度。

数据类型 (M,D)
#M称为精度,是数据的总长度,小数点不占位置;D参数称为标度,指小数点后的长度

浮点数在保存的时候经常会出一些意想不到的结果,建议使用DEC保存。

https://www.cnblogs.com/phpfensi/p/8143313.html
创建mysql数据表的时候,经常会遇到存储小数(浮点数)的情况,如:价格,重量,身高等。 目前大的公司流行三种存储方案: 、将数据扩大10的倍数达到使用整数类型存储目的。 比如价格,我们经常以分为单位进行存储,也就是将数据扩大100倍,这样元改成分存储。 重量可以用克为单位,如果克还是小数,就以毫克,微克等单位进行存储。 、使用decimal类型的方式存储 比如价格,我们可以使用两位小数的精度进行存储。强烈不建议采用float或者double的类型存储,会存在精度损失的问题,在以后做值比较的时候,容易出现不正确的结果。 、小数和整数部分分开存储。 比如价格3.,我们存成两个字段,一个字段存储3,一个字段存储14,一般情况下用的少。当存储的数据范围超出decimal的范围时,可以将数据按照整数和小数拆分。

MySQL中小数的存储

MySQL小数的存储,可以参照上面提到的方法!

日期与时间类型

日期与时间类型是为了方便在数据库中存储日期和时间而设定的。MySQL中有多种表示日期和时间的数据类型。其中,year表示时间,date表示日期,time表示实际;datetime和timestamp表示日期和时间。

类型 字节数 取值范围 零值
YEAR 1 1901~2155 0000
DATE 4 1000-01-01~9999~12-31 0000:00:00
TIME 3 -839:59:59~838:59:59 00:00:00
DATETIME 8 1000-01-01 00:00:00 ~9999~12-31 23:59:59 0000-00-00 00:00:00
TIMESTAMP(包含时区信息) 4 1970-01-01 08:00:01~2038-01-19 11:14:07 0000-00-00  00:00:00

每一种时间类型都有一个有效的范围。介绍一下Time类型。

TIME类型使用3个字节来表示时间。MySQL中以HH:MM:SS的形式显示TIME类型的值。其中,HH表示时,MM表示分,取值范围为0~59;SS表示秒,取值范围为0~59。虽然小时的范围是0~23,但是为表示某种特殊需要的时间间隔,将TIME类型的范围扩大了,而且还支持负数。

TIME类型的字段赋值表示方法如下:

“D HH:MM:SS”格式的字符串表示。其中,D表示天数,取值范围为0~。保存时,小时的值等于(D*+HH).
mysql> create table tb6(d time);
Query OK, rows affected (0.02 sec) mysql> insert into tb6 values("2 11:30:50");
Query OK, row affected (0.01 sec) mysql> select * from tb6;
+----------+
| d |
+----------+
| :: |
+----------+
row in set (0.00 sec) mysql>

在向数据库输入年份,日期的时候,MySQL有一些便捷的方法,但是推荐使用标准的输入,即没有缺省的输入!

字符类型

char类型和varchar类型都是在创建表时指定了最大长度,其基本形式如下:

字符串类型(M)        # M表示该字符串的最大长度为M,M指的是字符的个数,而不是字节!

char(M):表示该字段的字符串的最大长度为M,M取值范围为0~255之间的任意值。存储的占用的字节也是M字节固定不变的!
varhchar(M):表示字段的字符串最大长度为M,M取值范围为0~65535之间的任意值。指定为varchar类型之后,其长度可以在0到M(最大长度)之间。其占用的字节为,字符的实际字节数再加1.
一个实例:
在utf8中一个英文字母占用一个自己,一个汉字占用3个字节。
mysql> create table tb7(a char(5), b varchar(5));
Query OK, 0 rows affected (0.04 sec)
mysql> insert into tb7 values("a", "a"), ("bb","bb"); #插入数值
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0 mysql> select a, b from tb7;
+------+------+
| a    | b    | #这个记录中a占用5个字节,b占用2个字节
+------+------+
| a    | a    |
| bb   | bb   | #这个记录中a占用5个字节,b占用3个字节。
+------+------+
2 rows in set (0.00 sec) #插入汉字
mysql> insert into tb7 values("aaaaa","bbbbb");
Query OK, 1 row affected (0.01 sec) mysql> insert into tb7 values("上下左右中","上下左右中");
Query OK, 1 row affected (0.00 sec) mysql> select a, b from tb7;
+-----------------+-----------------+
| a               | b               |
+-----------------+-----------------+
| aaaaa           | bbbbb           | #这个记录a占用了5个字节,b占用了5+1个字节
| 上下左右中      | 上下左右中      | #这个记录中a占用了5*3=15个字节,b占用了5*3+1=16个字节
+-----------------+-----------------+
2 rows in set (0.00 sec) mysql>

特别注意: 通过以上的实例可以发现,char(M)和varchar(M)中的M指的是字符的个数,不是字节!

      那么M的取值范围,那个范围究竟是字节还是字符呢?

TEXT类型

TEXT类型是一种特殊的字符串类型。TEXT只保存字符数据。包含以下四种类型:

类型 允许长度 存储空间
TINYTEXT 0~255字节 存储的实际字节+2个字节
TEXT 0~65535字节 存储的实际字节+2个字节
MEDIUMTEXT 0~2^24-1字节 存储的实际字节+3个字节
LONGTEXT 0~2^32-1字节 存储的实际字节+4个字节

在实际存储时,可以根据不同需求选择不同的类型存储。

ENUM类型

ENUM类型又称为枚举类型。在创建表时,ENUM类型的取值范围就以列表的形式指定了。

属性名  ENUM("value1", "value2",...)
#ENUM类型的值只能取列表中的一个元素,取值列表最多有65535个元素。这些数值是以数组的形式存储,MySQL中存入的是数组的下标,而不是列表中的值。默认顺序,按数组的顺序排序。
#如果ENUM类型加上了 NOT NULL属性,其默认值为取值列表的第一个元素。如果不加NOT NULL 属性,ENUM允许插入空值,而且NULL为默认值。 mysql> create table tb8(a enum("a","b","c","d") not null, b enum("e","f","g"));
Query OK, 0 rows affected (0.03 sec) mysql> insert into tb8(a) values("a"); #b的默认值为空
Query OK, 1 row affected (0.02 sec) mysql> select * from tb8;
+---+------+
| a | b    |
+---+------+
| a | NULL |
+---+------+
1 row in set (0.00 sec) mysql> insert into tb8(b) values("e"); #的默认值为第一个字符“a”
Query OK, 1 row affected (0.01 sec) mysql> select * from tb8;
+---+------+
| a | b    |
+---+------+
| a | NULL |
| a | e    |
+---+------+
2 rows in set (0.00 sec) mysql> insert into tb8(b) values(1); #插入数字,表示对应数组的下标的值
Query OK, 1 row affected (0.00 sec) mysql> select * from tb8;
+---+------+
| a | b    |
+---+------+
| a | NULL |
| a | e    |
| a | e    |
+---+------+
3 rows in set (0.00 sec) mysql> insert into tb8(b) values(0); #插入0是会报错的,因此这里的数值下标从1开始。
ERROR 1265 (01000): Data truncated for column 'b' at row 1
mysql>

set类型

set类型与enum类型一样,区别在于set类型可以选取多个值,而enum类型只能选择一个值。

插入记录时,set字段中的元素顺序是无关紧要的,存入MySQL数据库后,数据库系统会自动按照定义时的顺序显示。

mysql> create table tb9(str1 set("a", "b", "c","d"), num set("one", "two","three") not null);  #创建一个表
Query OK, 0 rows affected (0.01 sec)
mysql> insert into tb9(str1,num) values("a,d", "one,three"); # 插入多个数据
Query OK, 1 row affected (0.02 sec) mysql> select * from tb9;
+------+-----------+
| str1 | num |
+------+-----------+
| a,d | one,three |
+------+-----------+
1 row in set (0.00 sec) mysql> insert into tb9(num) values("one,two"); #不设置not null默认数据为NULL
Query OK, 1 row affected (0.01 sec) mysql> select * from tb9;
+------+-----------+
| str1 | num |
+------+-----------+
| a,d | one,three |
| NULL | one,two |
+------+-----------+
2 rows in set (0.00 sec) mysql> insert into tb9(str1) values("c,d"); #设置NOT NULL默认数值,没有默认数值
ERROR 1364 (HY000): Field 'num' doesn't have a default value
mysql> insert into tb9(str1,num) values("d,b,a,a", "three, one"); #注意插入的多个数值之间不要有空格
ERROR 1265 (01000): Data truncated for column 'num' at row 1
mysql> insert into tb9(str1,num) values("d,b,a,a", "three,one"); #打乱顺序插入
Query OK, 1 row affected (0.00 sec) mysql> select * from tb9; #仍然是按照定义时的顺序存储的
+-------+-----------+
| str1  | num       |
+-------+-----------+
| a,d   | one,three |
| NULL  | one,two   |
| a,b,d | one,three |
+-------+-----------+
3 rows in set (0.00 sec) mysql>

二进制类型

二进制类型是在数据库中存储二进制数据的数据类型。包含以下几种:

项目 说明
BINARY(M) 字节长度为M,允许长度为0~M的定长二进制字符串
VARBINARY(M) 允许长度为0~M的变长二进制字符串,字节数为数值的字节数+1
BIT(M) M位二进制数据,M最大值为64
TINYBLOB 可变长二进制数据,最多为255个字节
BLOB 可变长二进制数据,最多为(2^16-1)个字节
MEDIUMBLOB 可变长二进制数据,最多为(2^24-1)个字节
LONGBLOB 可变长二进制数据,最多为(2^32-1)个字节

BLOB类型是一种特殊的二进制类型。BLOB类型可以用来数量很大的二进制数据,如图片等。但是通常情况下,可以把图片和文档存储在文件系统中,在BLOB中存入对应图片,文档的路径地址。但是这样,访问的速度可能会慢一点吧!

JSON类型:

在MySQL5.7中新增加了对JSON的支持。与在字符串列中存储json相比,数据类型有以下几点优势:

  • 自动验证在JSON列中存储的JSON文档,无效的列会报错。
  • 优化的存储格式。存储在JSON列中的JSON文档将 转换为内部格式,以允许快速读取文档元素。当服务器稍后必须读取以此二进制格式存储的JSON值时,不需要从文本表示中解析该值。二进制格式的结构使服务器能够直接通过键或数组索引查找子对象或嵌套值,而无需在文档中读取它们之前或之后的所有值。存储JSON所需的空间与LONGBLOB和LONGTEXT类型大致相同。请务必记住,JSON列中存储的任何JSON文档的大小都限制为max_allowed_packet系统变量的值。(当服务器在内存中内部操作JSON值时,它可能大于此值;当服务器存储时,该限制适用。)
  • JSON列没有默认值

虚构一张表,来说明MySQL5.7中JSON的用法:

#创建一张表
CREATE TABLE json_test (
id INT auto_increment PRIMARY KEY,
userinfo json
); #在表中插入json数据类型,JSON数据类型有两种,一种是JSON数组,另一种是JSON对象。
INSERT INTO json_test(userinfo) VALUES('{"name":"libai","address":"china","email":"libai@163.com"}');
INSERT INTO json_test(userinfo) VALUES('{"name":"Obama","address":"miguo","email":"libai@gmail.com"}');
INSERT INTO json_test(userinfo) VALUES('{"name":"putin","address":"russia","email":"putin@gmail.com"}');
### JSON对象包含一组由逗号分隔的键值对,并包含在字符{和}字符中:
INSERT INTO json_test(userinfo) VALUES('["wangxz","guangzhou","wangxz@163.com"]');
### JSON数组包含一个由逗号分隔的值列表

还可以插入JSON数组和JSON对象的嵌套:

INSERT INTO json_test(userinfo) VALUES('[5,{"id":1, "name":"lfy"}, ["a","b"]]');

如果插入无效的JSON数组和JSON对象将会报错。

除MySQL数据类型之外,还有一组SQL函数可用于对JSON值进行操作。

  

mysql> select * from json_test;
+----+--------------------------------------------------------------------+
| id | userinfo |
+----+--------------------------------------------------------------------+
| 1 | {"name": "libai", "email": "libai@163.com", "address": "china"} |
| 2 | {"name": "Obama", "email": "libai@gmail.com", "address": "miguo"} |
| 3 | {"name": "putin", "email": "putin@gmail.com", "address": "russia"} |
| 4 | ["wangxz", "guangzhou", "wangxz@163.com"] |
+----+--------------------------------------------------------------------+
4 rows in set (0.00 sec)
  • JSON_TYPE函数返回JSON的类型:
mysql> select json_type(userinfo) from json_test where id = 1;  #返回的是JSON对象类型
+---------------------+
| json_type(userinfo) |
+---------------------+
| OBJECT |
+---------------------+
1 row in set (0.00 sec) mysql> select json_type(userinfo) from json_test where id = 4; #返回的是数组类型
+---------------------+
| json_type(userinfo) |
+---------------------+
| ARRAY |
+---------------------+
1 row in set (0.00 sec) mysql>
  • 在向表中插入JSON类型时,可以借助于JSON_ARRAY()函数和JSON_OBJECT()函数,得到JSON数据类型。
mysql> select json_array("a", 1, now());
+----------------------------------------+
| json_array("a", 1, now()) |
+----------------------------------------+
| ["a", 1, "2018-10-05 09:20:23.000000"] |
+----------------------------------------+
1 row in set (0.00 sec) mysql> insert into json_test(userinfo) select json_array("a", 1, now());
Query OK, 1 row affected (0.02 sec)
Records: 1 Duplicates: 0 Warnings: 0 #这样在操作是不用去构造对应的JSON数组,可以借助于这个函数直接插入
mysql> select json_object("name","tump","address","miguo","email","tump@gmail.com");
+-----------------------------------------------------------------------+
| json_object("name","tump","address","miguo","email","tump@gmail.com") |
+-----------------------------------------------------------------------+
| {"name": "tump", "email": "tump@gmail.com", "address": "miguo"} |
+-----------------------------------------------------------------------+
1 row in set (0.00 sec) mysql> insert into json_test(userinfo) select json_object("name","tump","address","miguo","email","tump@gmail.com");
Query OK, 1 row affected (0.01 sec)
Records: 1 Duplicates: 0 Warnings: 0#JSON_OBJECT获取一个键值对列表,并返回包含这些对的JSON对象。
  • JSON_MERGE获取两个或多个文档的组合结果
mysql> select json_merge('["a","b"]', '{"key":"value"}');
+--------------------------------------------+
| json_merge('["a","b"]', '{"key":"value"}') |
+--------------------------------------------+
| ["a", "b", {"key": "value"}] |
+--------------------------------------------+
1 row in set, 1 warning (0.00 sec) mysql>
  • 可以将JSON值分配给用户定义的变量,但是定义的变量不能是JSON类型。
mysql> set @j = json_object("key","value");
Query OK, 0 rows affected (0.00 sec) mysql> select @j;
+------------------+
| @j |
+------------------+
| {"key": "value"} |
+------------------+
1 row in set (0.00 sec) mysql> select charset(@j), collation(@j);
+-------------+---------------+
| charset(@j) | collation(@j) |
+-------------+---------------+
| utf8mb4 | utf8mb4_bin |
+-------------+---------------+
1 row in set (0.00 sec) #通过转换生成的字符串具有以上的字符集和排序规则,utf8mb4_bin是二进制排序规则,所以区分大小写。
mysql> select json_array("x") = json_array("X");
+-----------------------------------+
| json_array("x") = json_array("X") |
+-----------------------------------+
| 0 |
+-----------------------------------+
1 row in set (0.00 sec) mysql> select json_valid("null"),json_valid("NULL"),json_valid("true"),json_valid(True);
+--------------------+--------------------+--------------------+------------------+
| json_valid("null") | json_valid("NULL") | json_valid("true") | json_valid(True) |
+--------------------+--------------------+--------------------+------------------+
| 1 | 0 | 1 | 0 |
+--------------------+--------------------+--------------------+------------------+
1 row in set (0.00 sec) 所以这些值null, true,false还是以小写的形式。
  • 把引号插入到JSON对象中
#使用json_object对象时,需要使用反斜线转义引号才能插入
mysql> insert into json_test(userinfo) values(json_object("mascot", "The mysql mascot is a dolphin named \"Sakila\"."));
Query OK, 1 row affected (0.00 sec) mysql> insert into json_test(userinfo) select json_object("mascot", "The mysql mascot is a dolphin named \"Sakila\".");
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
#把插入的值作为json对象插入时,需要使用双反斜线。
mysql> insert into json_test(userinfo) values('{"mascot":"The mysql mascot is a dolphin named \"Sakila\"."}');
ERROR 3140 (22032): Invalid JSON text: "Missing a comma or '}' after an object member." at position 49 in value for column 'json_test.userinfo'.
mysql> insert into json_test(userinfo) values('{"mascot":"The mysql mascot is a dolphin named \\"Sakila\\"."}');
Query OK, 1 row affected (0.01 sec) #使用双反斜线可以防止MySQL做转义处理,而是将字符串文字传递给存储引擎进行处理。
mysql> select * from json_test order by id desc limit 3;
+----+---------------------------------------------------------------+
| id | userinfo                                                      |
+----+---------------------------------------------------------------+
| 10 | {"mascot": "The mysql mascot is a dolphin named \"Sakila\"."} |
|  9 | {"mascot": "The mysql mascot is a dolphin named \"Sakila\"."} |
|  8 | {"mascot": "The mysql mascot is a dolphin named \"Sakila\"."} |
+----+---------------------------------------------------------------+
3 rows in set (0.00 sec) #查询数据可以看到反斜线的存在
查找JSON数据类型中,某一个key的值:
因为表中插入了测试数据,因此加上了where语句!
mysql> select userinfo->"$.address" from json_test where id <= 3; #注意格式
+-----------------------+
| userinfo->"$.address" |
+-----------------------+
| "china"               |
| "miguo"               |
| "russia"              |
+-----------------------+
3 rows in set (0.00 sec) mysql> select userinfo->"$.mascot" from json_test where id >7;
+---------------------------------------------------+
| userinfo->"$.mascot"                              |
+---------------------------------------------------+
| "The mysql mascot is a dolphin named \"Sakila\"." |
| "The mysql mascot is a dolphin named \"Sakila\"." |
| "The mysql mascot is a dolphin named \"Sakila\"." |
+---------------------------------------------------+
3 rows in set (0.00 sec) mysql> select userinfo->>"$.mascot" from json_test where id >7; #注意这一种与上面一种写法的区别,去掉了字符上的转义符
+-----------------------------------------------+
| userinfo->>"$.mascot"                         |
+-----------------------------------------------+
| The mysql mascot is a dolphin named "Sakila". |
| The mysql mascot is a dolphin named "Sakila". |
| The mysql mascot is a dolphin named "Sakila". |
+-----------------------------------------------+
3 rows in set (0.00 sec)

JSON值的规范化,合并和自动包装:

当解析一个字符串时,发现它是一个有效的JSON文档时,它就会被标准化。

json_object的过程就是一个标准化的过程。

json_merge将组合的后面的一个数组连接到前面一个数值的末尾,组合为单个数据。

mysql> select json_merge('[1,2]', '["a","b"]');
+----------------------------------+
| json_merge('[1,2]', '["a","b"]') |
+----------------------------------+
| [1, 2, "a", "b"] |
+----------------------------------+
1 row in set, 1 warning (0.00 sec) mysql>

合并时多个对象生成单个对象。如果多个对象具有相同的键,则生成的合并对象中该键的值是包含该键所有值的数值。

mysql> select json_merge('{"a":1,"b":2}', '{"a":3, "c":4}');
+-----------------------------------------------+
| json_merge('{"a":1,"b":2}', '{"a":3, "c":4}') |
+-----------------------------------------------+
| {"a": [1, 3], "b": 2, "c": 4} |
+-----------------------------------------------+
1 row in set, 1 warning (0.00 sec) mysql>

自动将两个字符合并为数组:

mysql> select json_merge("1", "2");
+----------------------+
| json_merge("1", "2") |
+----------------------+
| [1, 2] |
+----------------------+
1 row in set, 1 warning (0.00 sec) mysql>

通过将对象自动包装为数值,来合并数组和对象:

mysql> select json_merge('[1,2]', '{"a":1,"b":2}');
+--------------------------------------+
| json_merge('[1,2]', '{"a":1,"b":2}') |
+--------------------------------------+
| [1, 2, {"a": 1, "b": 2}] |
+--------------------------------------+
1 row in set, 1 warning (0.00 sec) mysql>

对JSON的操作:

  • JSON_EXTRACT---对于提取JSON文档的一部分或修改JSON文档的函数非常有用。
mysql> select json_extract('{"id":14, "name":"wangxz"}', "$.name");
+------------------------------------------------------+
| json_extract('{"id":14, "name":"wangxz"}', "$.name") |
+------------------------------------------------------+
| "wangxz" |
+------------------------------------------------------+
1 row in set (0.00 sec) #使用前导的$符合表示当前选中的JSON文档,后面采用如上的方式,选择提取文档中的数据
mysql> select json_extract(userinfo, "$.name") from json_test WHERE id <= 3; #json_extract在select语句中的使用
+----------------------------------+
| json_extract(userinfo, "$.name") |
+----------------------------------+
| "libai"                          |
| "Obama"                          |
| "putin"                          |
+----------------------------------+
3 rows in set (0.00 sec)

上面提到可以使用$符合来表示当前选中的JSON文档。在选择时$符合可以和通配符结合。

mysql> select json_extract('[5, {"id": 1, "name": "lfy"}, ["a", "b"]]', "$[*]"); #选择JSON数组中的所有元素的值
+-------------------------------------------------------------------+
| json_extract('[5, {"id": 1, "name": "lfy"}, ["a", "b"]]', "$[*]") |
+-------------------------------------------------------------------+
| [5, {"id": 1, "name": "lfy"}, ["a", "b"]] |
+-------------------------------------------------------------------+
1 row in set (0.00 sec) mysql> select json_extract('[5, {"id": 1, "name": "lfy"}, ["a", "b"]]', "$[]"); #选择JSON数组中的第一个元素
+-------------------------------------------------------------------+
| json_extract('[5, {"id": 1, "name": "lfy"}, ["a", "b"]]', "$[]") |
+-------------------------------------------------------------------+
| 5 |
+-------------------------------------------------------------------+
1 row in set (0.00 sec) mysql> select json_extract('[5, {"id": 1, "name": "lfy"}, ["a", "b"]]', "$[]"); #选择JSON数组中的第二个元素,这个JSON对象
+-------------------------------------------------------------------+
| json_extract('[5, {"id": 1, "name": "lfy"}, ["a", "b"]]', "$[]") |
+-------------------------------------------------------------------+
| {"id": 1, "name": "lfy"} |
+-------------------------------------------------------------------+
1 row in set (0.00 sec) mysql> select json_extract('[5, {"id": 1, "name": "lfy"}, ["a", "b"]]', "$[].id"); #选择JSON对象的id
+----------------------------------------------------------------------+
| json_extract('[5, {"id": 1, "name": "lfy"}, ["a", "b"]]', "$[].id") |
+----------------------------------------------------------------------+
| 1 |
+----------------------------------------------------------------------+
1 row in set (0.00 sec) mysql> select json_extract('[5, {"id": 1, "name": "lfy"}, ["a", "b"]]', "$[].name");
+------------------------------------------------------------------------+
| json_extract('[5, {"id": 1, "name": "lfy"}, ["a", "b"]]', "$[].name") |
+------------------------------------------------------------------------+
| "lfy" |
+------------------------------------------------------------------------+
1 row in set (0.00 sec) mysql> select json_extract('[5, {"id": 1, "name": "lfy"}, ["a", "b"]]', "$[][]");
+----------------------------------------------------------------------+
| json_extract('[5, {"id": 1, "name": "lfy"}, ["a", "b"]]', "$[][]") |
+----------------------------------------------------------------------+
| {"id": 1, "name": "lfy"} |
+----------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> select json_extract('[5, {"id": 1, "name": "lfy"}, ["a", "b"]]', "$[1].*"); #选择JSON对象中所有的成员的value值。
+---------------------------------------------------------------------+
| json_extract('[5, {"id": 1, "name": "lfy"}, ["a", "b"]]', "$[1].*") |
+---------------------------------------------------------------------+
| [1, "lfy"]                                                          |
+---------------------------------------------------------------------+
1 row in set (0.00 sec) mysql> mysql> select json_extract('[5, {"id": 1, "name": "lfy"}, ["a", "b"]]', "$[]");
+-------------------------------------------------------------------+
| json_extract('[5, {"id": 1, "name": "lfy"}, ["a", "b"]]', "$[]") |
+-------------------------------------------------------------------+
| ["a", "b"] |
+-------------------------------------------------------------------+
1 row in set (0.00 sec)
  • JSON_SET替换JSON文档中某个位置得数值,若是这个位置不存在,则在这个位置添加数值。
mysql> select userinfo from json_test WHERE id = 5;
+-------------------------------------------+
| userinfo |
+-------------------------------------------+
| [5, {"id": 1, "name": "lfy"}, ["a", "b"]] |
+-------------------------------------------+
1 row in set (0.00 sec) #表中有如上数据,我们把name的值改为wxz,最后一个数值中加入“c”
mysql> select json_set(userinfo, "$[].name", "wxz", "$[][]", "c") from json_test WHERE id = 5;
+--------------------------------------------------------+
| json_set(userinfo, "$[].name", "wxz", "$[][]", "c") |
+--------------------------------------------------------+
| [5, {"id": 1, "name": "wxz"}, ["a", "b", "c"]] |
+--------------------------------------------------------+
1 row in set (0.00 sec)
  • JSON_INSERT添加新的数值,但是不替换旧数值!
mysql> select userinfo from json_test WHERE id in (5,11);
+-------------------------------------------+
| userinfo |
+-------------------------------------------+
| [5, {"id": 1, "name": "lfy"}, ["a", "b"]] |
+-------------------------------------------+
1 row in set (0.01 sec)
#注意insert的作用,只是添加了字符“c”,并没有更改name键的值
mysql> select json_insert(userinfo, "$[].name", "wxz", "$[][]", "c") from json_test WHERE id = 5;
+-----------------------------------------------------------+
| json_insert(userinfo, "$[].name", "wxz", "$[][]", "c") |
+-----------------------------------------------------------+
| [5, {"id": 1, "name": "lfy"}, ["a", "b", "c"]] |
+-----------------------------------------------------------+
1 row in set (0.00 sec)
  • JSON_REPLACE:替换旧值,但是不能添加新值。
mysql> select json_replace(userinfo, "$[].name", "wxz", "$[][]", "c") from json_test WHERE id = 5;
+------------------------------------------------------------+
| json_replace(userinfo, "$[].name", "wxz", "$[][]", "c") |
+------------------------------------------------------------+
| [5, {"id": 1, "name": "wxz"}, ["a", "b"]] |
+------------------------------------------------------------+
1 row in set (0.00 sec) mysql>

JSON_REMOVE删除选择的数值。

mysql> select json_remove(userinfo, "$[].name", "$[][]") from json_test WHERE id = 5;
+-----------------------------------------------+
| json_remove(userinfo, "$[].name", "$[][]") |
+-----------------------------------------------+
| [5, {"id": 1}, ["a"]] |
+-----------------------------------------------+
1 row in set (0.00 sec) mysql>