MySQL中的JSON类型

JSON in MySQL

创建JSON值

一个JSON数组包含了一组由方括号包裹的,由逗号分隔的值:

["json", null, true, 123]

一个JSON对象包含了一组由花括号包裹的一组键值对,键值对之间用逗号分隔:

{"key": "value", "key2": 2}

JSON数组和对象可以包含字符串和数字这样纯量的值,JSON的null值字面量,或者JSON布尔值字面量(true/false)。在JSON对象中,键必须时字符串。表示时间的纯量值也可以在JSON中使用:

["2019-10-01 13:21:02.000022", "2011-09-28"]

在JSON数组,JSON对象中的value也可以嵌套使用JSON数组/对象,例如:

[100,{"name":"Jane", "age": 19},[21, 28]]
{"key1":[21,20], "key2":"value"}

JSON值可以通过MySQL提供的一些方法来创建,也可以使用CAST(value AS JSON)将其他类型的值转换为JSON类型。

在MySQL中,JSON值被写作为字符串。MySQL会在需要JSON值的环境下将任何字符串转换为JSON值,如果字符串不是一个有效的JSON值,MySQL会报错。这些环境包括:向某个数据类型为JSON的字段插入数据时,或是向某个参数类型为JSON的函数传入参数时等。

除了使用字面量编写JSON值外,还有一些函数可以将各部分的值组合成JSON值。

例如:JSON_ARRAY()接收一组值,返回一个包含了这些值的JSON数组;

mysql> SELECT JSON_ARRAY('a', 1, NOW());
+----------------------------------------+
| JSON_ARRAY('a', 1, NOW())              |
+----------------------------------------+
| ["a", 1, "2019-04-23 10:34:07.000000"] |
+----------------------------------------+
1 row in set (0.01 sec)

JSON_OBJECT()接收一系列的键值对,返回一个包含了这些键值对的JSON对象。如果输入的参数列表中,键值对的键名发生了重复,先输入的键值对(位于参数列表前端)将被覆盖,输出的结果中只包含重复键值对中最后一个输入的值(位于参数列表尾端);

mysql> SELECT JSON_OBJECT('key1','value1','key2',2);
+---------------------------------------+
| JSON_OBJECT('key1','value1','key2',2) |
+---------------------------------------+
| {"key1": "value1", "key2": 2}         |
+---------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_OBJECT('key1',1,'key2','abc','key1','def');
+-------------------------------------------------+
| JSON_OBJECT('key1',1,'key2','abc','key1','def') |
+-------------------------------------------------+
| {"key1": "def", "key2": "abc"}                  |
+-------------------------------------------------+
1 row in set (0.00 sec)

JSON_MERGE_PRESERVE()接收两个或两个以上的JSON文件,返回一个合并后的结果;

mysql> SELECT JSON_MERGE_PRESERVE('{"key1":1,"key2":2}','[2,"abc"]');
+--------------------------------------------------------+
| JSON_MERGE_PRESERVE('{"key1":1,"key2":2}','[2,"abc"]') |
+--------------------------------------------------------+
| [{"key1": 1, "key2": 2}, 2, "abc"]                     |
+--------------------------------------------------------+
1 row in set (0.00 sec)

JSON值是大小写敏感的,因此在使用null,true,false这些字面量时,一定要使用小写字母。相比之下,SQL中的字面量NULL,TRUE,FALSE则是大小写不敏感的,可以使用任何形式来表示。

MySQL中支持两种合并方法,JSON_MERGE_PRESERVE()JSON_MERGE_PATCH()。二者的区别在于如何处理重复的键:JSON_MERGE_PRESERVE()保留重复的键,而JSON_MERGE_PATCH()只保留最后一个值,其他值都会被丢弃。

  • 合并数组

    JSON_MERGE_PRESERVE()会将所有数组拼接起来形成一个新数组并返回。而JSON_MERGE_PATCH()只会保留最后一个数组,并将其作为结果返回。

    mysql> SELECT JSON_MERGE_PRESERVE('[1,2]','["A","B"]','[true,false]');
    +---------------------------------------------------------+
    | JSON_MERGE_PRESERVE('[1,2]','["A","B"]','[true,false]') |
    +---------------------------------------------------------+
    | [1, 2, "A", "B", true, false]                           |
    +---------------------------------------------------------+
    1 row in set (0.00 sec)
    
    mysql> SELECT JSON_MERGE_PATCH('[1,2]','["A","B"]','[true,false]');
    +------------------------------------------------------+
    | JSON_MERGE_PATCH('[1,2]','["A","B"]','[true,false]') |
    +------------------------------------------------------+
    | [true, false]                                        |
    +------------------------------------------------------+
    1 row in set (0.00 sec)
    
  • 合并对象

    当要合并的多个对象中含有相同的键时,JSON_MERGE_PRESERVE()会将重复的键对应的所有值去重后存入一个数组中作为该键的值,再将该键值对存入对象中返回。JSON_MERGE_PATCH()则会从左到右依次丢弃重复键的值,只保留最后一个出现的值。

    mysql> SELECT JSON_MERGE_PERSERVE('{"a":1,"b":2}','{"c":3,"a":4}','{"c":5,"d":3}');
    ERROR 1046 (3D000): No database selected
    mysql> SELECT JSON_MERGE_PRESERVE('{"a":1,"b":2}','{"c":3,"a":4}','{"c":5,"d":3}');
    +----------------------------------------------------------------------+
    | JSON_MERGE_PRESERVE('{"a":1,"b":2}','{"c":3,"a":4}','{"c":5,"d":3}') |
    +----------------------------------------------------------------------+
    | {"a": [1, 4], "b": 2, "c": [3, 5], "d": 3}                           |
    +----------------------------------------------------------------------+
    1 row in set (0.00 sec)
    
    mysql> SELECT JSON_MERGE_PATCH('{"a":1,"b":2}','{"c":3,"a":4}','{"c":5,"d":3}'); 
    +-------------------------------------------------------------------+
    | JSON_MERGE_PATCH('{"a":1,"b":2}','{"c":3,"a":4}','{"c":5,"d":3}') |
    +-------------------------------------------------------------------+
    | {"a": 4, "b": 2, "c": 5, "d": 3}                                  |
    +-------------------------------------------------------------------+
    1 row in set (0.00 sec)
    
  • 合并值

    当传入的参数既不是数组,也不是对象,而是单独的值时,这个值会被自动用方括号包裹转换成数组,然后按照合并数组的规则进行合并。

    mysql> SELECT JSON_MERGE_PRESERVE('1','2');
    +------------------------------+
    | JSON_MERGE_PRESERVE('1','2') |
    +------------------------------+
    | [1, 2]                       |
    +------------------------------+
    1 row in set (0.00 sec)
    
    mysql> SELECT JSON_MERGE_PATCH('1','2');
    +---------------------------+
    | JSON_MERGE_PATCH('1','2') |
    +---------------------------+
    | 2                         |
    +---------------------------+
    1 row in set (0.00 sec)
    
  • 合并数组和对象

    当合并的对象既有数组也有对象时,对象会被自动包装转换成数组进行合并操作,然后按照合并数组的规则进行合并。

    mysql> SELECT JSON_MERGE_PRESERVE('[10,11]','{"key1": 1, "key2": 2}');
    +---------------------------------------------------------+
    | JSON_MERGE_PRESERVE('[10,11]','{"key1": 1, "key2": 2}') |
    +---------------------------------------------------------+
    | [10, 11, {"key1": 1, "key2": 2}]                        |
    +---------------------------------------------------------+
    1 row in set (0.00 sec)
    
    mysql> SELECT JSON_MERGE_PATCH('[10,11]','{"key1": 1, "key2": 2}');
    +------------------------------------------------------+
    | JSON_MERGE_PATCH('[10,11]','{"key1": 1, "key2": 2}') |
    +------------------------------------------------------+
    | {"key1": 1, "key2": 2}                               |
    +------------------------------------------------------+
    1 row in set (0.00 sec)
    
    

搜索和修改JSON值

一个路径表达式(path expression)可以在一个JSON文档中选择一个值。当我们需要从一个JSON文档中提取或者修改一部分值时,路径表达式十分有用,我们可以使用路径表达式明确得指出需要修改的部分。

路径表达式的语法使用一个先导的$来代表需要进行操作的JSON文档,具体的语法如下:

pathExpression:
    scope[(pathLeg)*]

pathLeg:
    member | arrayLocation | doubleAsterisk

member:
    period ( keyName | asterisk )

arrayLocation:
    leftBracket ( nonNegativeInteger | asterisk ) rightBracket

keyName:
    ESIdentifier | doubleQuotedString

doubleAsterisk:
    '**'

period:
    '.'

asterisk:
    '*'

leftBracket:
    '['

rightBracket:
    ']'

大体上讲,.可以选择某个键对应的值,[]可以选择数组中的某个值或者某个范围的值,*通配符可以选择某个指定范围的值。与路径表达式配合使用一些方法,可以实现搜索和修改JSON值,这些方法常见的有:

JSON_EXTRACT()—提取某个值

mysql> SELECT JSON_EXTRACT('{"a":1,"b":2,"c":[3,4,5]}','$.c[*]');
+----------------------------------------------------+
| JSON_EXTRACT('{"a":1,"b":2,"c":[3,4,5]}','$.c[*]') |
+----------------------------------------------------+
| [3, 4, 5]                                          |
+----------------------------------------------------+
1 row in set (0.00 sec)

JSON_SET()—若路径对应的值存在,替换这个值,如果不存在则添加新值。

mysql> SELECT JSON_SET('{"key1":1, "key2":2}', '$.key1', 2);
+-----------------------------------------------+
| JSON_SET('{"key1":1, "key2":2}', '$.key1', 2) |
+-----------------------------------------------+
| {"key1": 2, "key2": 2}                        |
+-----------------------------------------------+
1 row in set (0.00 sec)

JSON_INSERT()—添加新值,但是不替换已经存在的值(忽略旧值)

mysql> SELECT JSON_INSERT('[1,2,3]', '$[0]', 0, '$[3]', 4);
+----------------------------------------------+
| JSON_INSERT('[1,2,3]', '$[0]', 0, '$[3]', 4) |
+----------------------------------------------+
| [1, 2, 3, 4]                                 |
+----------------------------------------------+
1 row in set (0.01 sec)

JSON_REPLACE()—替换已经存在的值,忽略新值

mysql> SELECT JSON_REPLACE('[1,2,3]', '$[0]', 0, '$[3]', 4);
+-----------------------------------------------+
| JSON_REPLACE('[1,2,3]', '$[0]', 0, '$[3]', 4) |
+-----------------------------------------------+
| [0, 2, 3]                                     |
+-----------------------------------------------+
1 row in set (0.00 sec)

JSON_REMOVE()—删除某个值

mysql> SELECT JSON_REMOVE('[[1,2],{"key1":1, "key2":"value2"}]', '$[1].key1');
+-----------------------------------------------------------------+
| JSON_REMOVE('[[1,2],{"key1":1, "key2":"value2"}]', '$[1].key1') |
+-----------------------------------------------------------------+
| [[1, 2], {"key2": "value2"}]                                    |
+-----------------------------------------------------------------+
1 row in set (0.00 sec)

比较和排序JSON值

JSON值可以通过使用=,<,<=,>,>=,<>,!=<=>操作符进行比较。

JSON值不支持使用一下操作符/函数进行比较:

  • BETWEEN
  • IN()
  • GREATEST()
  • LEAST()

你可能感兴趣的:(MySQL中的JSON类型)