MySQL8.0新特性學習筆記(五):JSON格式簡介和JSON函數詳解

目錄

JSON格式簡介

定義用戶變量

JSON格式的規範化

JSON的路徑表達式

JSON的比較和排序

JSON的函數

一,創建JSON格式數據

1,JSON_ARRAY([val[, val] ...])

2,JSON_OBJECT([key, val[, key, val] ...])

3,JSON_QUOTE(string)

二,JSON的查詢

1,JSON_CONTAINS(target, candidate[, path])

2,JSON_CONTAINS_PATH(json_doc, one_or_all, path[, path] ...)

3,JSON_EXTRACT(json_doc, path[, path] ...)

4,->運算符

5,->>運算符

6,JSON_KEYS(json_doc[, path])

7,JSON_OVERLAPS(json_doc1, json_doc2)

8,JSON_SEARCH(json_doc, one_or_all, search_str[, escape_char[, path] ...])

9,value MEMBER OF(json_array)

三,JSON值的修改

1,JSON_ARRAY_APPEND(json_doc, path, val[, path, val] ...)

2,JSON_ARRAY_INSERT(json_doc, path, val[, path, val] ...)

3,JSON_INSERT(json_doc, path, val[, path, val] ...)

4,JSON_MERGE(json_doc, json_doc[, json_doc] ...)

5,JSON_MERGE_PATCH(json_doc, json_doc[, json_doc] ...)

6,JSON_MERGE_PRESERVE(json_doc, json_doc[, json_doc] ...)

7,JSON_REMOVE(json_doc, path[, path] ...)

8,JSON_REPLACE(json_doc, path, val[, path, val] ...)

9,JSON_SET(json_doc, path, val[, path, val] ...)

10,JSON_UNQUOTE(json_val)

四,JSON值的屬性

1,JSON_DEPTH(json_doc)

2,JSON_LENGTH(json_doc[, path])

3,JSON_TYPE(json_val)

4,JSON_VALID(val)

五,JSON臨時表函數

六,JSON格式校驗

1,JSON_SCHEMA_VALID(schema,document)

2,JSON_SCHEMA_VALIDATION_REPORT(schema,document)

七,JSON輔助函數

1,JSON_PRETTY(json_val)

2,JSON_STORAGE_FREE(json_val)

3,JSON_STORAGE_SIZE(json_val)


JSON格式簡介

MySQL8.0開始支持JSON格式,可以對JSON格式的數據進行高效的訪問。

和原來JSON格式的字符串相比,JSON格式有以下的優點:

1,自動驗證。錯誤的JSON格式會報錯。

2,存儲格式優化。數據保存爲二進制格式,文件存儲很緊湊,讀取速度快。

3,MySQL可以通過鍵或數組索引查詢和修改對應的值,不用把整個字符串都讀出來。

 

一些其他的介紹:

1,JSON格式需要的磁盤空間和longblob或longtext差不多。

2,JSON格式的默認值只能是null。

3,JSON格式的列不能直接建立索引,可以建立JSON索引。

4,JSON格式的key必須是字符串格式。value可以是字符串,數字,布爾型。

5,JSON格式默認使用utf8mb4字符集,utf8mb4-bin排序,其他字符集使用JSON格式需要做字符集轉換。ascii或utf8不用轉換,他們是utf8mb4的子集。

6,大小寫敏感,而且true,false,null這些關鍵字在JSON格式裏都必須小寫。說白了就是:null,Null,NULL,都是null,但是"Null"無法轉成null,只有"null"才能轉成null。

比如:

mysql> SELECT JSON_ARRAY('x') = JSON_ARRAY('X');
+-----------------------------------+
| JSON_ARRAY('x') = JSON_ARRAY('X') |
+-----------------------------------+
|                                 0 |
+-----------------------------------+

mysql> SELECT JSON_VALID('null'), JSON_VALID('Null'), JSON_VALID('NULL');
+--------------------+--------------------+--------------------+
| JSON_VALID('null') | JSON_VALID('Null') | JSON_VALID('NULL') |
+--------------------+--------------------+--------------------+
|                  1 |                  0 |                  0 |
+--------------------+--------------------+--------------------+

mysql> SELECT CAST('null' AS JSON);
+----------------------+
| CAST('null' AS JSON) |
+----------------------+
| null                 |
+----------------------+
1 row in set (0.00 sec)

mysql> SELECT CAST('NULL' AS JSON);
ERROR 3141 (22032): Invalid JSON text in argument 1 to function cast_as_json:
"Invalid value." at position 0 in 'NULL'.

mysql> SELECT ISNULL(null), ISNULL(Null), ISNULL(NULL);
+--------------+--------------+--------------+
| ISNULL(null) | ISNULL(Null) | ISNULL(NULL) |
+--------------+--------------+--------------+
|            1 |            1 |            1 |
+--------------+--------------+--------------+

7,JSON格式中包含單引號或雙引號時,需要用一條反斜線來轉義。

8,JSON格式會丟棄一些額外的空格,並且會把鍵值對排序。

 

 

定義用戶變量

使用例子:

mysql> SET @j = JSON_OBJECT('key', 'value');
mysql> SELECT @j;
+------------------+
| @j               |
+------------------+
| {"key": "value"} |
+------------------+

注意,定義的用戶變量不再是JSON格式,而是String格式,這個是在賦值給變量的時候轉的。另外,變量的字符集和排序規則和JSON格式相同:utf8mb4和utf8mb4_bin:

mysql> SELECT CHARSET(@j), COLLATION(@j);
+-------------+---------------+
| CHARSET(@j) | COLLATION(@j) |
+-------------+---------------+
| utf8mb4     | utf8mb4_bin   |
+-------------+---------------+

 

JSON格式的規範化

當產生JSON格式的數據時,MySQL會把JSON規範化,當有相同的key存在時,後面的key會覆蓋前面的key。8.0.3及之前版本有bug。

舉例:

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

mysql> CREATE TABLE t1 (c1 JSON);

mysql> INSERT INTO t1 VALUES
     >     ('{"x": 17, "x": "red"}'),
     >     ('{"x": 17, "x": "red", "x": [3, 5, 7]}');

mysql> SELECT c1 FROM t1;
+------------------+
| c1               |
+------------------+
| {"x": "red"}     |
| {"x": [3, 5, 7]} |
+------------------+

 

JSON的路徑表達式

MySQL用路徑表達式對JSON格式的數據進行查詢。

  • 路徑表達式中用$代表JSON值。
  • 用key值代表該key對應的元素。
  • 用[N]代表JSON數組中的第N個元素。序號從0開始。
  • 用[M to N]代表JSON數組中第M個至第N個元素。序號從0開始。
  • 用.[*]通配符代表JSON對象的所有子元素。
  • 用[*]通配符代表JSON數組的所有元素。
  • 用**通配符代表用某字符開頭或結尾的元素。

 

在JSON數組中查詢

如果用$代表以下JSON:

[3, {"a": [5, 6], "b": 10}, [99, 100]]

那麼:

  • $[0] 指向 3。
  • $[1] 指向 {"a": [5, 6], "b": 10}。
  • $[2] 指向 [99, 100]。
  • $[3] 指向 NULL。因爲沒有第四個元素。
  • $[1].a 指向 [5, 6]。
  • $[1].a[1] 指向 6。
  • $[1].b 指向 10。
  • $[2][0] 指向 99。

注意到$[1].a中的a可以不寫引號。而如果key名中有空格,則必須加引號,見後面的例子。

 

在JSON對象中查詢

如果用$代表以下JSON:

{"a fish": "shark", "a bird": "sparrow"}

那麼:

  • $."a fish" 指向 shark。
  • $."a bird" 指向 sparrow。

注意,"a fish"這個key值中有空格,所以引號是必須加的。

 

*通配符的查詢:

mysql> SELECT JSON_EXTRACT('{"a": 1, "b": 2, "c": [3, 4, 5]}', '$.*');
+---------------------------------------------------------+
| JSON_EXTRACT('{"a": 1, "b": 2, "c": [3, 4, 5]}', '$.*') |
+---------------------------------------------------------+
| [1, 2, [3, 4, 5]]                                       |
+---------------------------------------------------------+
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]                                                  |
+------------------------------------------------------------+

 

**通配符的查詢:

mysql> SELECT JSON_EXTRACT('{"a": {"b": 1}, "c": {"b": 2}}', '$**.b');
+---------------------------------------------------------+
| JSON_EXTRACT('{"a": {"b": 1}, "c": {"b": 2}}', '$**.b') |
+---------------------------------------------------------+
| [1, 2]                                                  |
+---------------------------------------------------------+

 

正序範圍查詢

範圍查詢使用[M to N]這樣的表達式,注意序號是從0開始的,比如:

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

 

倒序範圍查詢

倒序查詢使用[last-M to last-N]這樣的表達式,注意逆向的序號也是從0開始的,比如:

mysql> SELECT JSON_EXTRACT('[1, 2, 3, 4, 5]', '$[last-3 to last-1]');
+--------------------------------------------------------+
| JSON_EXTRACT('[1, 2, 3, 4, 5]', '$[last-3 to last-1]') |
+--------------------------------------------------------+
| [2, 3, 4]                                              |
+--------------------------------------------------------+
1 row in set (0.01 sec)

注意,如果last關鍵字用於非數組時,效果等同於先把目標對象封裝成單元素數組,然後再操作,比如:

mysql> SELECT JSON_REPLACE('"Sakila"', '$[last]', 10);
+-----------------------------------------+
| JSON_REPLACE('"Sakila"', '$[last]', 10) |
+-----------------------------------------+
| 10                                      |
+-----------------------------------------+
1 row in set (0.00 sec)

 

JSON的比較和排序

可支持的操作符:=, <, <=, >, >=, <>, !=, and <=>

不支持的操作符:BETWEEN,IN(),GREATEST(),LEAST()。可以把JSON中的值解析出來然後用可支持的操作符來做判斷。

JSON值的比較有數據類型優先級的概念,不同優先級的數據類型比較時,由較高優先級的類型決定。數據類型的優先級從大到小分別是:

  • BLOB
  • BIT
  • OPAQUE
  • DATETIME
  • TIME
  • DATE
  • BOOLEAN
  • ARRAY
  • OBJECT
  • STRING
  • INTEGER, DOUBLE
  • NULL

下面分別介紹一下排序規則:

1,BLOB

比較兩個JSON值的前N個字符,N是較短值中的字節數。如果前N個字符相同,較短值排在較大值前面。

2,BIT

同BLOB。

3,OPAQUE

同BLOB。

4,DATETIME

按時間排序。

5,TIME

按時間排序。

6,DATE

按時間排序。

7,BOOLEAN

false小於true。可能原理是false=0,true=1。

8,ARRAY

由數組中第一個不同元素決定大小,如果較短數組的全部元素都等於較長數組中的對應元素,則短數組排在前面。比如:

[] < ["a"] < ["ab"] < ["ab", "cd", "ef"] < ["ab", "ef"]

9,OBJECT

如果兩個JSON對象有相同的鍵集,而且每個鍵對應的值都相等,那麼兩個JSON對象就相等。

10,STRING

比較兩個JSON值的前N個字符,N是較短值中的字符數。如果前N個字符相同,較短值排在較大值前面。

11,INTEGER, DOUBLE

比較數字大小。

12,NULL

如果比較雙方有NULL,比較的結果爲UNKNOWN。

 

JSON的函數

 

一,創建JSON格式數據

 

1,JSON_ARRAY([val[, val] ...])

根據參數值創建JSON數組,每個參數都是數組中一個元素。

舉例:

mysql> SELECT JSON_ARRAY(1, "abc", NULL, TRUE, CURTIME());
+---------------------------------------------+
| JSON_ARRAY(1, "abc", NULL, TRUE, CURTIME()) |
+---------------------------------------------+
| [1, "abc", null, true, "10:27:46.000000"]   |
+---------------------------------------------+
1 row in set (0.00 sec)

 

2,JSON_OBJECT([key, val[, key, val] ...])

根據參數列表創建JSON對象。

按照參數的排列,第一個是key,第二個是value,第三個是key,以此類推。參數個數必須是雙數。

參數列表可以爲空,得到空JSON:{}。

key不能是null。否則報錯。value可以是null。

數據類型錯誤時會報錯。

舉例:

mysql> SELECT JSON_OBJECT('id', 87, 'name', 'carrot');
+-----------------------------------------+
| JSON_OBJECT('id', 87, 'name', 'carrot') |
+-----------------------------------------+
| {"id": 87, "name": "carrot"}            |
+-----------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_OBJECT('id', 87, null, 'carrot');  
ERROR 3158 (22032): JSON documents may not contain NULL member names.

mysql> SELECT JSON_OBJECT('id', 87, 'name', NULL);
+-------------------------------------+
| JSON_OBJECT('id', 87, 'name', NULL) |
+-------------------------------------+
| {"id": 87, "name": null}            |
+-------------------------------------+
1 row in set (0.00 sec)

 

3,JSON_QUOTE(string)

用雙引號把字符串括起來,把結果轉爲utf8mb4並返回。其中會經過JSON的轉義。目的是得到JSON的字符串形式。

mysql> SELECT JSON_QUOTE('null'), JSON_QUOTE('"null"');
+--------------------+----------------------+
| JSON_QUOTE('null') | JSON_QUOTE('"null"') |
+--------------------+----------------------+
| "null"             | "\"null\""           |
+--------------------+----------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_QUOTE('[1, 2, 3]');
+-------------------------+
| JSON_QUOTE('[1, 2, 3]') |
+-------------------------+
| "[1, 2, 3]"             |
+-------------------------+
1 row in set (0.01 sec)

 

二,JSON的查詢

 

1,JSON_CONTAINS(target, candidate[, path])

檢查候選JSON是否包含在目標JSON中,1表示包含,0表示不包含。

target是目標元素,candidate是候選元素,path是路徑表達式,如果path有值,則目標元素需要先經過路徑表達式的處理再參與判斷。

此函數可以使用多值索引。

另有如下規則:

1)參數可比時才能使用此函數。json_type()相同時才能使用此函數,另外integer和decimal類型可以直接比。

2)數組包含在數組中。只有目標數組的每個元素都包含在候選數組中,纔算包含。

3)非數組包含在數組中。只有候選JSON對象包含在目標數組的某個元素中,纔算包含。

4)非數組包含在非數組中。當且僅當候選JSON對象的每個key,在目標JSON對象中都有同名的key和同值的value,纔算包含。

比如:

mysql> SELECT JSON_CONTAINS('{"a": 1, "b": 2, "c": {"d": 4}}', '1', '$.a');     
+--------------------------------------------------------------+
| JSON_CONTAINS('{"a": 1, "b": 2, "c": {"d": 4}}', '1', '$.a') |
+--------------------------------------------------------------+
|                                                            1 |
+--------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_CONTAINS('{"a": 1, "b": 2, "c": {"d": 4}}', '1', '$.b');
+--------------------------------------------------------------+
| JSON_CONTAINS('{"a": 1, "b": 2, "c": {"d": 4}}', '1', '$.b') |
+--------------------------------------------------------------+
|                                                            0 |
+--------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_CONTAINS('{"a": 1, "b": 2, "c": {"d": 4}}', '{"d":4}', '$.b');
+--------------------------------------------------------------------+
| JSON_CONTAINS('{"a": 1, "b": 2, "c": {"d": 4}}', '{"d":4}', '$.b') |
+--------------------------------------------------------------------+
|                                                                  0 |
+--------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_CONTAINS('{"a": 1, "b": 2, "c": {"d": 4}}', '{"d":4}', '$.c');
+--------------------------------------------------------------------+
| JSON_CONTAINS('{"a": 1, "b": 2, "c": {"d": 4}}', '{"d":4}', '$.c') |
+--------------------------------------------------------------------+
|                                                                  1 |
+--------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_CONTAINS('{"a": 1, "b": 2, "c": {"d": 4}}', "{\"d\":4}", '$.c');    
+----------------------------------------------------------------------+
| JSON_CONTAINS('{"a": 1, "b": 2, "c": {"d": 4}}', "{\"d\":4}", '$.c') |
+----------------------------------------------------------------------+
|                                                                    1 |
+----------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_CONTAINS('{"a": 1, "b": 2, "c": {"d": 4}}', "{\"d\":\"4\"}", '$.c');
+--------------------------------------------------------------------------+
| JSON_CONTAINS('{"a": 1, "b": 2, "c": {"d": 4}}', "{\"d\":\"4\"}", '$.c') |
+--------------------------------------------------------------------------+
|                                                                        0 |
+--------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_CONTAINS('["abc","def"]','"abc"');
+----------------------------------------+
| JSON_CONTAINS('["abc","def"]','"abc"') |
+----------------------------------------+
|                                      1 |
+----------------------------------------+

注意,候選JSON和目標JSON都得是JSON格式的字符串,單個元素也得加引號,數字要寫成這樣:"1",字符串要引號外面再套引號,寫成這樣:'"abc"'。

 

2,JSON_CONTAINS_PATH(json_doc, one_or_all, path[, path] ...)

判斷目標JSON中是否存在指定的路徑或路徑列表。

第一個參數是目標JSON。

第二個參數可以選擇oneall。如果選擇one,那麼只要其中一條路徑是存在的就返回1,否則返回0。如果選擇all,那麼必須所有路徑都存在才返回1,否則返回0。

舉例:

mysql> SELECT JSON_CONTAINS_PATH('{"a": 1, "b": 2, "c": {"d": 4}}', 'one', '$.a', '$.e');  
+----------------------------------------------------------------------------+
| JSON_CONTAINS_PATH('{"a": 1, "b": 2, "c": {"d": 4}}', 'one', '$.a', '$.e') |
+----------------------------------------------------------------------------+
|                                                                          1 |
+----------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_CONTAINS_PATH('{"a": 1, "b": 2, "c": {"d": 4}}', 'all', '$.a', '$.e');   
+----------------------------------------------------------------------------+
| JSON_CONTAINS_PATH('{"a": 1, "b": 2, "c": {"d": 4}}', 'all', '$.a', '$.e') |
+----------------------------------------------------------------------------+
|                                                                          0 |
+----------------------------------------------------------------------------+
1 row in set (0.00 sec)

 

3,JSON_EXTRACT(json_doc, path[, path] ...)

從目標JSON中返回對應路徑下的元素。如果匹配到多個元素則封裝成數組。

比如:

mysql> SELECT JSON_EXTRACT('[10, 20, [30, 40]]', '$[1]');
+--------------------------------------------+
| JSON_EXTRACT('[10, 20, [30, 40]]', '$[1]') |
+--------------------------------------------+
| 20                                         |
+--------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_EXTRACT('[10, 20, [30, 40]]', '$[1]', '$[0]');
+----------------------------------------------------+
| JSON_EXTRACT('[10, 20, [30, 40]]', '$[1]', '$[0]') |
+----------------------------------------------------+
| [20, 10]                                           |
+----------------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_EXTRACT('[10, 20, [30, 40]]', '$[2][*]');
+-----------------------------------------------+
| JSON_EXTRACT('[10, 20, [30, 40]]', '$[2][*]') |
+-----------------------------------------------+
| [30, 40]                                      |
+-----------------------------------------------+
1 row in set (0.00 sec)

 

4,->運算符

此運算符是JSON_EXTRACT()函數的簡寫,單個path的場景。

這個運算符幾乎可以出現在sql的所有位置,而且在select,update等語句中都能用,比如:

mysql> SELECT c, JSON_EXTRACT(c, "$.id"), g
     > FROM jemp
     > WHERE JSON_EXTRACT(c, "$.id") > 1
     > ORDER BY JSON_EXTRACT(c, "$.name");

這個語句可以替換爲:

mysql> SELECT c, c->"$.id", g
     > FROM jemp
     > WHERE c->"$.id" > 1
     > ORDER BY c->"$.name";

另外,在EXPLAIN結果的WARING中,->表達式被展開成json_extract()函數:

mysql> explain select a->'$.name' from test_j;
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table  | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------+
|  1 | SIMPLE      | test_j | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    2 |   100.00 | NULL  |
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

mysql> SHOW WARNINGS;
+-------+------+------------------------------------------------------------------------------------------------------+
| Level | Code | Message                                                                                              |
+-------+------+------------------------------------------------------------------------------------------------------+
| Note  | 1003 | /* select#1 */ select json_extract(`dev`.`test_j`.`a`,'$.name') AS `a->'$.name'` from `dev`.`test_j` |
+-------+------+------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

 

5,->>運算符

->>運算符是加強版的->運算符,他把->運算符得到的結果去掉了引號,就像JSON_UNQUOTE ()函數一樣,所以,以下三個表達式所代表的含義是一樣的:

  • JSON_UNQUOTE( JSON_EXTRACT(column, path) )
  • JSON_UNQUOTE(column -> path)
  • column->>path

和->>運算符一樣,->>運算符可以被用到sql中的很多位置。

舉例:

mysql> select * from test_j;
+-------------------------------+
| a                             |
+-------------------------------+
| {"id": "3", "name": "Barney"} |
| {"id": "4", "name": "Betty"}  |
+-------------------------------+
2 rows in set (0.00 sec)

mysql> select a->'$.name' from test_j;
+-------------+
| a->'$.name' |
+-------------+
| "Barney"    |
| "Betty"     |
+-------------+
2 rows in set (0.00 sec)

mysql> select a->>'$.name' from test_j;
+--------------+
| a->>'$.name' |
+--------------+
| Barney       |
| Betty        |
+--------------+
2 rows in set (0.00 sec)

另外,和->運算符一樣,在EXPLAIN語句結果中,->>運算符會被展開:

mysql> explain select a->>'$.name' from test_j;
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table  | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------+
|  1 | SIMPLE      | test_j | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    2 |   100.00 | NULL  |
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

mysql> SHOW WARNINGS;
+-------+------+---------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message                                                                                                             |
+-------+------+---------------------------------------------------------------------------------------------------------------------+
| Note  | 1003 | /* select#1 */ select json_unquote(json_extract(`dev`.`test_j`.`a`,'$.name')) AS `a->>'$.name'` from `dev`.`test_j` |
+-------+------+---------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

 

6,JSON_KEYS(json_doc[, path])

返回JSON中一級鍵值對中key的列表。如果寫了path字段,則先進行路徑表達式計算,然後的返回第一級鍵值對中key的列表。

也就是說,不會返回子元素的key。

mysql> SELECT JSON_KEYS('{"a": 1, "b": {"c": 30}}');
+---------------------------------------+
| JSON_KEYS('{"a": 1, "b": {"c": 30}}') |
+---------------------------------------+
| ["a", "b"]                            |
+---------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_KEYS('{"a": 1, "b": {"c": 30}}', '$.b');
+----------------------------------------------+
| JSON_KEYS('{"a": 1, "b": {"c": 30}}', '$.b') |
+----------------------------------------------+
| ["c"]                                        |
+----------------------------------------------+
1 row in set (0.00 sec)

 

7,JSON_OVERLAPS(json_doc1, json_doc2)

比較兩個JSON是否有相同元素。也就是是否有交集。有則返回1,沒有返回0。

部分匹配的情況不能算有相同元素。

兩個JSON對象比較時,兩者至少有一個相同name的key和相同對應value,則返回1。

兩個標量比較時,則比較值是否相等。

標量和數組比較時,則判斷標量是否和數組某元素相等。數據類型不同時不算相等。

比如:

mysql> SELECT JSON_OVERLAPS("[1,3,5,7]", "[2,5,7]");
+---------------------------------------+
| JSON_OVERLAPS("[1,3,5,7]", "[2,5,7]") |
+---------------------------------------+
|                                     1 |
+---------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_OVERLAPS("[1,3,5,7]", "[2,6,8]");
+---------------------------------------+
| JSON_OVERLAPS("[1,3,5,7]", "[2,6,8]") |
+---------------------------------------+
|                                     0 |
+---------------------------------------+
1 row in set (0.00 sec)

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

mysql> SELECT JSON_OVERLAPS('{"a":1,"b":10,"d":10}', '{"a":5,"e":10,"f":1,"d":20}');
+-----------------------------------------------------------------------+
| JSON_OVERLAPS('{"a":1,"b":10,"d":10}', '{"a":5,"e":10,"f":1,"d":20}') |
+-----------------------------------------------------------------------+
|                                                                     0 |
+-----------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_OVERLAPS('[4,5,"6",7]', '6');
+-----------------------------------+
| JSON_OVERLAPS('[4,5,"6",7]', '6') |
+-----------------------------------+
|                                 0 |
+-----------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_OVERLAPS('[4,5,6,7]', '"6"');
+-----------------------------------+
| JSON_OVERLAPS('[4,5,6,7]', '"6"') |
+-----------------------------------+
|                                 0 |
+-----------------------------------+
1 row in set (0.00 sec)

 

8,JSON_SEARCH(json_doc, one_or_all, search_str[, escape_char[, path] ...])

根據某字符串,返回在目標JSON中匹配的value的路徑表達式,search_str和JSON中的value相等時算匹配。

此函數能查詢子元素信息。

第一個參數json_doc是目標JSON。

第二個參數one_or_all可以選擇one或者all。one表示返回一個匹配的值的路徑。all表示返回所有路徑。

參數search_str是要搜索的字符串。其中可以用%(百分號)代表任意多個字符,_(下劃線)代表任意一個字符。

參數escape_char是轉義字符。默認是\。寫成空字符串或NULL時,也默認爲\。

參數path是路徑表達式,如果寫了path,匹配結果需在路徑表達式下進行。

比如:

mysql> SELECT JSON_SEARCH('["abc", [{"k": "10"}, "def"], {"x":"abc"}, {"y":"bcd"}]', 'one', 'abc');  
+--------------------------------------------------------------------------------------+
| JSON_SEARCH('["abc", [{"k": "10"}, "def"], {"x":"abc"}, {"y":"bcd"}]', 'one', 'abc') |
+--------------------------------------------------------------------------------------+
| "$[0]"                                                                               |
+--------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_SEARCH('["abc", [{"k": "10"}, "def"], {"x":"abc"}, {"y":"bcd"}]', 'all', 'abc');   
+--------------------------------------------------------------------------------------+
| JSON_SEARCH('["abc", [{"k": "10"}, "def"], {"x":"abc"}, {"y":"bcd"}]', 'all', 'abc') |
+--------------------------------------------------------------------------------------+
| ["$[0]", "$[2].x"]                                                                   |
+--------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_SEARCH('["abc", [{"k": "10"}, "def"], {"x":"abc"}, {"y":"bcd"}]', 'all', 'abcdefg');
+------------------------------------------------------------------------------------------+
| JSON_SEARCH('["abc", [{"k": "10"}, "def"], {"x":"abc"}, {"y":"bcd"}]', 'all', 'abcdefg') |
+------------------------------------------------------------------------------------------+
| NULL                                                                                     |
+------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_SEARCH('["abc", [{"k": "10"}, "def"], {"x":"abc"}, {"y":"bcd"}]', 'all', '10', NULL, '$[1][0].k');
+--------------------------------------------------------------------------------------------------------+
| JSON_SEARCH('["abc", [{"k": "10"}, "def"], {"x":"abc"}, {"y":"bcd"}]', 'all', '10', NULL, '$[1][0].k') |
+--------------------------------------------------------------------------------------------------------+
| "$[1][0].k"                                                                                            |
+--------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_SEARCH('["abc", [{"k": "10"}, "def"], {"x":"abc"}, {"y":"bcd"}]', 'all', '%b%', NULL, '$[3]');
+----------------------------------------------------------------------------------------------------+
| JSON_SEARCH('["abc", [{"k": "10"}, "def"], {"x":"abc"}, {"y":"bcd"}]', 'all', '%b%', NULL, '$[3]') |
+----------------------------------------------------------------------------------------------------+
| "$[3].y"                                                                                           |
+----------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

 

9,value MEMBER OF(json_array)

判斷value是否被包含在某JSON數組中。包含則返回1,否則返回0。

數據格式不同時不算包含。

value可以用其他表達式替代。

JSON格式的字符串不能直接和數組中的JSON對象比較,會返回0,此時需要把value轉成JSON類型才能返回1。

mysql> SELECT 17 MEMBER OF('[23, "abc", 17, "ab", 10]');
+-------------------------------------------+
| 17 MEMBER OF('[23, "abc", 17, "ab", 10]') |
+-------------------------------------------+
|                                         1 |
+-------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT '17' MEMBER OF('[23, "abc", 17, "ab", 10]');
+---------------------------------------------+
| '17' MEMBER OF('[23, "abc", 17, "ab", 10]') |
+---------------------------------------------+
|                                           0 |
+---------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_ARRAY(4,5) MEMBER OF('[[3,4],[4,5]]');
+--------------------------------------------+
| JSON_ARRAY(4,5) MEMBER OF('[[3,4],[4,5]]') |
+--------------------------------------------+
|                                          1 |
+--------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT '{"a":1}' MEMBER OF(JSON_ARRAY(17, CAST('{"a":1}' AS JSON), "abc", 23));
+-------------------------------------------------------------------------+
| '{"a":1}' MEMBER OF(JSON_ARRAY(17, CAST('{"a":1}' AS JSON), "abc", 23)) |
+-------------------------------------------------------------------------+
|                                                                       0 |
+-------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT CAST('{"a":1}' AS JSON) MEMBER OF(JSON_ARRAY(17, CAST('{"a":1}' AS JSON), "abc", 23));
+---------------------------------------------------------------------------------------+
| CAST('{"a":1}' AS JSON) MEMBER OF(JSON_ARRAY(17, CAST('{"a":1}' AS JSON), "abc", 23)) |
+---------------------------------------------------------------------------------------+
|                                                                                     1 |
+---------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

 

三,JSON值的修改

1,JSON_ARRAY_APPEND(json_doc, path, val[, path, val] ...)

向JSON數組中追加元素,如果對應位置是單個元素,則和新元素一起封裝成數組。

另外,在MySQL8.0中,原來的JSON_APPEND()函數不再使用。

mysql> SELECT JSON_ARRAY_APPEND('["a", ["b", "c"], "d"]', '$[1]', 1);
+--------------------------------------------------------+
| JSON_ARRAY_APPEND('["a", ["b", "c"], "d"]', '$[1]', 1) |
+--------------------------------------------------------+
| ["a", ["b", "c", 1], "d"]                              |
+--------------------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_ARRAY_APPEND('["a", ["b", "c"], "d"]', '$[1][0]', 3);  
+-----------------------------------------------------------+
| JSON_ARRAY_APPEND('["a", ["b", "c"], "d"]', '$[1][0]', 3) |
+-----------------------------------------------------------+
| ["a", [["b", 3], "c"], "d"]                               |
+-----------------------------------------------------------+
1 row in set (0.01 sec)

mysql> SELECT JSON_ARRAY_APPEND('{"a": 1}', '$', 'z');  
+-----------------------------------------+
| JSON_ARRAY_APPEND('{"a": 1}', '$', 'z') |
+-----------------------------------------+
| [{"a": 1}, "z"]                         |
+-----------------------------------------+
1 row in set (0.00 sec)

 

2,JSON_ARRAY_INSERT(json_doc, path, val[, path, val] ...)

在數組的指定位置追加元素,原位置的元素和後面的元素依次向後移一位。

指定位置超過數組上限,則添加在數組最後位置。

注意:在多個位置添加多個元素時,添加是有順序的,後面添加的元素需要等前面的元素添加成功後重新確認具體位置。

舉例:

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

mysql> SELECT JSON_ARRAY_INSERT('["a", {"b": [1, 2]}, [3, 4]]', '$[100]', 'x');
+------------------------------------------------------------------+
| JSON_ARRAY_INSERT('["a", {"b": [1, 2]}, [3, 4]]', '$[100]', 'x') |
+------------------------------------------------------------------+
| ["a", {"b": [1, 2]}, [3, 4], "x"]                                |
+------------------------------------------------------------------+
1 row in set (0.00 sec)

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

mysql> SELECT JSON_ARRAY_INSERT('["a", {"b": [1, 2]}, [3, 4]]', '$[0]', 'x', '$[2][1]', 'y');  
+--------------------------------------------------------------------------------+
| JSON_ARRAY_INSERT('["a", {"b": [1, 2]}, [3, 4]]', '$[0]', 'x', '$[2][1]', 'y') |
+--------------------------------------------------------------------------------+
| ["x", "a", {"b": [1, 2]}, [3, 4]]                                              |
+--------------------------------------------------------------------------------+
1 row in set (0.00 sec)

注意最後一個語句,在$[0]處添加x,在$[2][1]處添加y,但是最後y沒有添加成功,本來$[2]代表的應該是[3, 4],但是前面添加了x後,JSON變成了:

["x", "a", {"b": [1, 2]}, [3, 4]]

於是此時的$[2]變成了{"b": [1, 2]},是個JSON對象,不是數組,所以無法使用此函數。

以下sql可以驗證這個場景:

mysql> SELECT JSON_ARRAY_INSERT('["a", {"b": [1, 2]}, [3, 4]]', '$[0]', 'x', '$[2].b[1]', 'y');
+----------------------------------------------------------------------------------+
| JSON_ARRAY_INSERT('["a", {"b": [1, 2]}, [3, 4]]', '$[0]', 'x', '$[2].b[1]', 'y') |
+----------------------------------------------------------------------------------+
| ["x", "a", {"b": [1, "y", 2]}, [3, 4]]                                           |
+----------------------------------------------------------------------------------+
1 row in set (0.00 sec)

可見添加y的時候$[2]已經是{"b": [1, 2]}了。

 

3,JSON_INSERT(json_doc, path, val[, path, val] ...)

向JSON添加鍵值對。

如果添加的key已經存在,則忽略此鍵值對,不再添加。

mysql> SELECT JSON_INSERT('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.c', '[true, false]');      
+--------------------------------------------------------------------------+
| JSON_INSERT('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.c', '[true, false]') |
+--------------------------------------------------------------------------+
| {"a": 1, "b": [2, 3], "c": "[true, false]"}                              |
+--------------------------------------------------------------------------+
1 row in set (0.00 sec)

從此結果可以看到,此函數不支持數據類型轉換,'[true, false]'參數被當做字符串添加了,如果需要作爲JSON數組添加,需要手動轉換:

mysql> SELECT JSON_INSERT('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.c', CAST('[true, false]' AS JSON));
+----------------------------------------------------------------------------------------+
| JSON_INSERT('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.c', CAST('[true, false]' AS JSON)) |
+----------------------------------------------------------------------------------------+
| {"a": 1, "b": [2, 3], "c": [true, false]}                                              |
+----------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

 

4,JSON_MERGE(json_doc, json_doc[, json_doc] ...)

合併多個JSON,MySQL8.0.3版本已廢棄,建議使用JSON_MERGE_PRESERVE()函數。

舉例:

mysql> SELECT JSON_MERGE('[1, 2]', '[true, false]');
+---------------------------------------+
| JSON_MERGE('[1, 2]', '[true, false]') |
+---------------------------------------+
| [1, 2, true, false]                   |
+---------------------------------------+
1 row in set, 1 warning (0.00 sec)

mysql> SHOW WARNINGS;
+---------+------+-----------------------------------------------------------------------------------------------------------------------------+
| Level   | Code | Message                                                                                                                     |
+---------+------+-----------------------------------------------------------------------------------------------------------------------------+
| Warning | 1287 | 'JSON_MERGE' is deprecated and will be removed in a future release. Please use JSON_MERGE_PRESERVE/JSON_MERGE_PATCH instead |
+---------+------+-----------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

 

5,JSON_MERGE_PATCH(json_doc, json_doc[, json_doc] ...)

合併多個JSON對象。會去重的合併。

合併規則:

1,如果兩JSON合併,第一個JSON不是對象(比如標量或數組),則合併的結果是第二個JSON,即使第二個JSON也不是對象。

2,如果兩JSON合併,第二個JSON不是對象(比如標量或數組),則合併的結果還是第二個JSON。爲什麼?這什麼道理?

3,如果兩個JSON中有相同的key,且value中有非對象,則value保留後面JSON的value。

4,如果兩個JSON中有相同的key,且對應的value中都是JSON對象,則兩個value遞歸合併。

5,合併完成後,value是null的鍵值對會被刪掉。可以用這個特性來刪除空值鍵值對,比如用一個標量和想刪null值的JSON合併,記得標量放第一位,JSON放第二位。

mysql> SELECT JSON_MERGE_PATCH('[1, 2]', '[true, false]');
+---------------------------------------------+
| JSON_MERGE_PATCH('[1, 2]', '[true, false]') |
+---------------------------------------------+
| [true, false]                               |
+---------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_MERGE_PATCH('{"a":1, "b":2, "c":null}', '[]');
+----------------------------------------------------+
| JSON_MERGE_PATCH('{"a":1, "b":2, "c":null}', '[]') |
+----------------------------------------------------+
| []                                                 |
+----------------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_MERGE_PATCH('{ "a": 1, "b":2 }','{ "a": 3, "c":4 }','{ "a": 5, "d":6 }');
+-------------------------------------------------------------------------------+
| JSON_MERGE_PATCH('{ "a": 1, "b":2 }','{ "a": 3, "c":4 }','{ "a": 5, "d":6 }') |
+-------------------------------------------------------------------------------+
| {"a": 5, "b": 2, "c": 4, "d": 6}                                              |
+-------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_MERGE_PATCH('{"a":{"x":1}}', '{"a":{"y":2}}');
+----------------------------------------------------+
| JSON_MERGE_PATCH('{"a":{"x":1}}', '{"a":{"y":2}}') |
+----------------------------------------------------+
| {"a": {"x": 1, "y": 2}}                            |
+----------------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_MERGE_PATCH('1','{"a":1, "b":2, "c":null}');
+--------------------------------------------------+
| JSON_MERGE_PATCH('1','{"a":1, "b":2, "c":null}') |
+--------------------------------------------------+
| {"a": 1, "b": 2}                                 |
+--------------------------------------------------+
1 row in set (0.00 sec)

 

6,JSON_MERGE_PRESERVE(json_doc, json_doc[, json_doc] ...)

合併多個JSON。不去重,保留所有值的合併。

合併規則:

1,兩數組或兩標量合併,合成一個新數組。

2,兩對象合併,遞歸合併成一個新對象。如有同key鍵值對,則幾個value合併成最終的value。

3,對象和數組合並,對象轉成單個元素的數組然後合併成一個新數組。

舉例:

mysql> SELECT JSON_MERGE_PRESERVE('[1, 2]', '[true, false]');
+------------------------------------------------+
| JSON_MERGE_PRESERVE('[1, 2]', '[true, false]') |
+------------------------------------------------+
| [1, 2, true, false]                            |
+------------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_MERGE_PRESERVE('{"name": "x"}', '{"id": 47}');
+----------------------------------------------------+
| JSON_MERGE_PRESERVE('{"name": "x"}', '{"id": 47}') |
+----------------------------------------------------+
| {"id": 47, "name": "x"}                            |
+----------------------------------------------------+
1 row in set (0.00 sec)

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

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

感覺這個JSON_MERGE_PRESERVE()函數纔是真正的合併,不漏元素。相比之下JSON_MERGE_PATCH()函數的作用更像是去重。

 

7,JSON_REMOVE(json_doc, path[, path] ...)

從JSON中刪除對應路徑下的元素。

指定路徑不存在也不會報錯。

mysql> SELECT JSON_REMOVE('["a", ["b", "c"], "d"]', '$[1]');   
+-----------------------------------------------+
| JSON_REMOVE('["a", ["b", "c"], "d"]', '$[1]') |
+-----------------------------------------------+
| ["a", "d"]                                    |
+-----------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_REMOVE('["a", ["b", "c"], "d"]', '$[9]');
+-----------------------------------------------+
| JSON_REMOVE('["a", ["b", "c"], "d"]', '$[9]') |
+-----------------------------------------------+
| ["a", ["b", "c"], "d"]                        |
+-----------------------------------------------+
1 row in set (0.00 sec)

 

8,JSON_REPLACE(json_doc, path, val[, path, val] ...)

替換JSON中的值。

如果路徑不存在,則忽略。

mysql> SELECT JSON_REPLACE('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.c', '[true, false]');  
+---------------------------------------------------------------------------+
| JSON_REPLACE('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.c', '[true, false]') |
+---------------------------------------------------------------------------+
| {"a": 10, "b": [2, 3]}                                                    |
+---------------------------------------------------------------------------+
1 row in set (0.00 sec)

 

9,JSON_SET(json_doc, path, val[, path, val] ...)

替換JSON中的值。

如果路徑不存在,則添加該值。

如果修改的是數組,路徑超過了數組上限,則把元素添加到數組末尾。

mysql> SELECT JSON_SET('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.c', '[true, false]');  
+-----------------------------------------------------------------------+
| JSON_SET('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.c', '[true, false]') |
+-----------------------------------------------------------------------+
| {"a": 10, "b": [2, 3], "c": "[true, false]"}                          |
+-----------------------------------------------------------------------+
1 row in set (0.00 sec)

所以,JSON_SET(),JSON_INSERT(),和JSON_REPLACE()三者的區別在於:

  • JSON_SET():路徑存在則替換值,路徑不存在則新增。
  • JSON_INSERT():只負責新增。
  • JSON_REPLACE():只負責替換已存在的值。

 

10,JSON_UNQUOTE(json_val)

去掉JSON值的雙引號,並返回utf8mb4格式的字符串。

此函數可以識別轉義字符。

mysql> SELECT '"abc"', JSON_UNQUOTE('"abc"');
+-------+-----------------------+
| "abc" | JSON_UNQUOTE('"abc"') |
+-------+-----------------------+
| "abc" | abc                   |
+-------+-----------------------+
1 row in set (0.00 sec)

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

mysql> SELECT JSON_UNQUOTE('"\\t\\u0032"');
+------------------------------+
| JSON_UNQUOTE('"\\t\\u0032"') |
+------------------------------+
|       2                           |
+------------------------------+

 

四,JSON值的屬性

1,JSON_DEPTH(json_doc)

返回JSON值的最大深度。

空數組,空對象,標量的深度爲1。

僅包含深度爲1的元素的數組或對象的深度爲2。

其他情況以此類推。

舉例:

mysql> SELECT JSON_DEPTH('{}'), JSON_DEPTH('[]'), JSON_DEPTH('true');
+------------------+------------------+--------------------+
| JSON_DEPTH('{}') | JSON_DEPTH('[]') | JSON_DEPTH('true') |
+------------------+------------------+--------------------+
|                1 |                1 |                  1 |
+------------------+------------------+--------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_DEPTH('[10, 20]'), JSON_DEPTH('[[], {}]');
+------------------------+------------------------+
| JSON_DEPTH('[10, 20]') | JSON_DEPTH('[[], {}]') |
+------------------------+------------------------+
|                      2 |                      2 |
+------------------------+------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_DEPTH('[10, {"a": 20}]');
+-------------------------------+
| JSON_DEPTH('[10, {"a": 20}]') |
+-------------------------------+
|                             3 |
+-------------------------------+
1 row in set (0.00 sec)

 

2,JSON_LENGTH(json_doc[, path])

返回JSON值的長度。如果寫了path,返回對應路徑下的JSON長度。

標量的長度是1。

數組的長度是元素的數量。

對象的長度是成員數量。

嵌套的數組不會被計算長度。

舉例:

mysql> SELECT JSON_LENGTH('[1, 2, {"a": 3}]');
+---------------------------------+
| JSON_LENGTH('[1, 2, {"a": 3}]') |
+---------------------------------+
|                               3 |
+---------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_LENGTH('{"a": 1, "b": {"c": 30}}');
+-----------------------------------------+
| JSON_LENGTH('{"a": 1, "b": {"c": 30}}') |
+-----------------------------------------+
|                                       2 |
+-----------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_LENGTH('{"a": 1, "b": {"c": 30}}', '$.b');
+------------------------------------------------+
| JSON_LENGTH('{"a": 1, "b": {"c": 30}}', '$.b') |
+------------------------------------------------+
|                                              1 |
+------------------------------------------------+
1 row in set (0.00 sec)

 

3,JSON_TYPE(json_val)

返回JSON類型。返回值是一個utf8mb4字符串。

可返回的JSON類型有:

  1. OBJECT。JSON對象。
  2. ARRAY。JSON數組。
  3. BOOLEAN。JSON的true或false。
  4. NULL。JSON的null值。這個返回值是大寫的。
  5. INTEGER。TINYINT,SMALLINT,MEDIUMINT,INT,BIGINT類型標量。
  6. DOUBLE。DOUBLE和FLOAT類型標量。
  7. DECIMAL。DECIMAL和NUMERIC類型標量。
  8. DATETIME。DATETIME和TIMESTAMP類型標量。
  9. DATE。DATE類型標量。
  10. TIME。TIME類型標量。
  11. STRING。MySQL中utf8格式標量,比如:CHAR,VARCHAR,TEXT,ENUM,SET。
  12. BLOB。MySQL中二進制格式標量,比如:BINARY,VARBINARY,BLOB,BIT。
  13. OPAQUE。raw bits格式。

舉例:

mysql> SELECT JSON_TYPE('{"a": [10, true]}');
+--------------------------------+
| JSON_TYPE('{"a": [10, true]}') |
+--------------------------------+
| OBJECT                         |
+--------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_TYPE(JSON_EXTRACT('{"a": [10, true]}', '$.a[1]'));  
+--------------------------------------------------------+
| JSON_TYPE(JSON_EXTRACT('{"a": [10, true]}', '$.a[1]')) |
+--------------------------------------------------------+
| BOOLEAN                                                |
+--------------------------------------------------------+
1 row in set (0.00 sec)

 

4,JSON_VALID(val)

判斷JSON值是否符合JSON規範。符合返回1,不符合返回0。

mysql> SELECT JSON_VALID('{"a": 1}');
+------------------------+
| JSON_VALID('{"a": 1}') |
+------------------------+
|                      1 |
+------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_VALID('hello'), JSON_VALID('"hello"');
+---------------------+-----------------------+
| JSON_VALID('hello') | JSON_VALID('"hello"') |
+---------------------+-----------------------+
|                   0 |                     1 |
+---------------------+-----------------------+
1 row in set (0.00 sec)

 

五,JSON臨時表函數

JSON臨時表函數可以把一個JSON值變成一個臨時表,並返回表格的一些信息。

建立臨時表的函數如下:

JSON_TABLE(

    expr,

    path COLUMNS (column_list)

)   [AS] alias

解析一下其中的各個表達式:

1,expr是JSON值。可以是個常量,比如'{"a":1}'。可以是一列值,比如t1.json_data,t1是之前定義的JSON臨時表。可以是返回JSON值的函數,比如:JSON_EXTRACT(t1,jsn_data,'$.post.comments')。

2,path是路徑表達式,JSON值要先經過路徑表達式的篩選。

3,alias是臨時表的表名。AS可以不寫。

4,COLUMNS是臨時表的列。當列中用到path路徑時,$從父級路徑表達式繼承,屬於相對路徑。

 

COLUMNS的單個元素都可以有以下選擇:

1),name FOR ORDINALITY

此列代表行號。name是自定義列名。此列內容是一個自增的計數器,類型是unsigned int,初始爲1。類似MySQL的自增id。如果列中包含NESTED PATH語句,會把一行拆成多行,此時這些行的行號都是一樣的,也就是第一級行的行號。

2),name type PATH string_path [on_empty] [on_error]

此列表示按照路徑表達式查詢JSON中的值。name是列名。type是要求返回的數據格式。string_path是路徑表達式。

 

[on_empty]用於路徑表達式值不存在的時候的默認值。

[on_empty]可選的寫法有:

NULL ON EMPTY。顯示爲NULL,此爲默認方式。

ERROR ON EMPTY。顯示爲ERROR。

DEFAULT json_string ON EMPTY。顯示一個默認的JSON值。

 

[on_error]用於路徑表達式下報錯的時候的默認值。報錯的場景比如保存時的精度錯誤,格式錯誤等。

[on_error]可選的寫法有:

NULL ON ERROR。顯示爲NULL,此爲默認方式。

ERROR ON ERROR。顯示爲ERROR。

DEFAULT json_string ON ERROR。顯示一個默認的JSON值。

下面是一個使用ON EMPTY和ON ERROR的例子:

mysql>  SELECT *
    ->  FROM
    ->    JSON_TABLE(
    ->      '[{"a":"3"},{"a":2},{"b":1},{"a":0},{"a":[1,2]}]',
    ->      "$[*]"
    ->      COLUMNS(
    ->        rowid FOR ORDINALITY,
    ->        ac VARCHAR(100) PATH "$.a" DEFAULT '111' ON EMPTY DEFAULT '999' ON ERROR
    ->      )
    ->    ) AS tt;
+-------+------+
| rowid | ac   |
+-------+------+
|     1 | 3    |
|     2 | 2    |
|     3 | 111  |
|     4 | 0    |
|     5 | 999  |
+-------+------+
5 rows in set (0.01 sec)

可見,第3行從{"b":1}獲取"$.a"時不存在,顯示的是ON EMPTY的默認值111。

第5行從{"a":[1,2]}獲取"$.a"時得到了數組,而不是列中定義的VARCHAR(100),類型錯誤,顯示的是ON ERROR默認的999。

3),name type EXISTS PATH path

指定路徑下的值是否存在。存在返回1,不存在返回0。

4),NESTED [PATH] path COLUMNS (column_list)

將JSON中嵌套結構的JSON對象或數組元素拆成單獨的行。

[PATH]關鍵字可以不寫。

column_list可以寫多個,可寫的內容和臨時表函數可用的column_list一樣,name FOR ORDINALITY之類的都可以寫。

對於同一元素中的PATH和NESTED PATH,得到的結果類似一個內連接。

如果存在多個NESTED PATH,則會對每個NESTED PATH單獨生成一組記錄,不會用連接的形式展示。

舉例:

mysql> SELECT *
    -> FROM
    ->   JSON_TABLE(
    ->     '[ {"a": 1, "b": [11,111]}, {"a": 2, "b": [22,222]}, {"a":3}]',
    ->     '$[*]' COLUMNS(
    ->             id FOR ORDINALITY,
    ->             a INT PATH '$.a',
    ->             NESTED PATH '$.b[*]' COLUMNS (b INT PATH '$')
    ->            )
    ->    ) AS jt
    -> WHERE b IS NOT NULL;
+------+------+------+
| id   | a    | b    |
+------+------+------+
|    1 |    1 |   11 |
|    1 |    1 |  111 |
|    2 |    2 |   22 |
|    2 |    2 |  222 |
+------+------+------+
4 rows in set (0.00 sec)

可以看到,前兩行id都是1,他們都是從數組的第一個元素{"a": 1, "b": [11,111]}得來的,這兩行的a列和b列就類似'$.a'和'$.b[*]'的一個內連接。

再比如:

mysql> SELECT *
    -> FROM
    ->   JSON_TABLE(
    ->     '[{"a": 1, "b": [11,111]}, {"a": 2, "b": [22,222,2222]}]',
    ->     '$[*]' COLUMNS(
    ->         a INT PATH '$.a',
    ->         NESTED PATH '$.b[*]' COLUMNS (b1 INT PATH '$'),
    ->         NESTED PATH '$.b[*]' COLUMNS (b2 INT PATH '$')
    ->     )
    -> ) AS jt;
+------+------+------+
| a    | b1   | b2   |
+------+------+------+
|    1 |   11 | NULL |
|    1 |  111 | NULL |
|    1 | NULL |   11 |
|    1 | NULL |  111 |
|    2 |   22 | NULL |
|    2 |  222 | NULL |
|    2 | 2222 | NULL |
|    2 | NULL |   22 |
|    2 | NULL |  222 |
|    2 | NULL | 2222 |
+------+------+------+
10 rows in set (0.00 sec)

可以看到,前4條數據是由{"a": 1, "b": [11,111]}得來的,b1和b2列理論上能獲得11和111兩個值,但是查詢結果給b1和b2分別生成了2條記錄。後6條數據是由{"a": 2, "b": [22,222,2222]}得來的,b1和b2列能獲得22,222,2222三個值,但是查詢結果給b1和b2分別生成了3條記錄。

稍微複雜一點的情況:

mysql> SELECT *
    -> FROM
    ->   JSON_TABLE(
    ->     '[{"a": "a_val",
    '>       "b": [{"c": "c_val", "l": [1,2]}]},
    '>     {"a": "a_val",
    '>       "b": [{"c": "c_val","l": [11]}, {"c": "c_val", "l": [22]}]}]',
    ->     '$[*]' COLUMNS(
    ->       top_ord FOR ORDINALITY,
    ->       apath VARCHAR(10) PATH '$.a',
    ->       NESTED PATH '$.b[*]' COLUMNS (
    ->         bpath VARCHAR(10) PATH '$.c',
    ->         ord FOR ORDINALITY,
    ->         NESTED PATH '$.l[*]' COLUMNS (lpath varchar(10) PATH '$')
    ->         )
    ->     )
    -> ) as jt;
+---------+-------+-------+------+-------+
| top_ord | apath | bpath | ord  | lpath |
+---------+-------+-------+------+-------+
|       1 | a_val | c_val |    1 | 1     |
|       1 | a_val | c_val |    1 | 2     |
|       2 | a_val | c_val |    1 | 11    |
|       2 | a_val | c_val |    2 | 22    |
+---------+-------+-------+------+-------+
4 rows in set (0.00 sec)

 

 

六,JSON格式校驗

1,JSON_SCHEMA_VALID(schema,document)

校驗document文檔是否符合schema定義的JSON規則。

document和schema必須都是標準的JSON格式。

schema中的require參數表示必須要有的key。

假如定義一個schema:

mysql> SET @schema = '{
    '>  "id": "http://json-schema.org/geo",
    '>  "$schema": "http://json-schema.org/draft-04/schema#",
    '>  "description": "A geographical coordinate",
    '>  "type": "object",
    '>  "properties": {
    '>   "latitude": {
    '>     "type": "number",
    '>     "minimum": -90,
    '>     "maximum": 90
    '>   },
    '>   "longitude": {
    '>     "type": "number",
    '>     "minimum": -180,
    '>     "maximum": 180
    '>   }
    '>  },
    '>  "required": ["latitude", "longitude"]
    '> }';
Query OK, 0 rows affected (0.00 sec)

然後定義document:

mysql> SET @document = '{
    '>  "latitude": 63.444697,
    '>  "longitude": 10.445118
    '> }';
Query OK, 0 rows affected (0.00 sec)

最後用JSON_SCHEMA_VALID(schema,document)函數來校驗:

mysql> SELECT JSON_SCHEMA_VALID(@schema, @document);
+---------------------------------------+
| JSON_SCHEMA_VALID(@schema, @document) |
+---------------------------------------+
|                                     1 |
+---------------------------------------+
1 row in set (0.00 sec)

返回1即爲符合schema定義的規範。

下面把document改成空的:

mysql> SET @document = '{}';
Query OK, 0 rows affected (0.00 sec)

再校驗一下:

mysql> SELECT JSON_SCHEMA_VALID(@schema, @document);
+---------------------------------------+
| JSON_SCHEMA_VALID(@schema, @document) |
+---------------------------------------+
|                                     0 |
+---------------------------------------+
1 row in set (0.00 sec)

返回0表示校驗失敗。

 

2,JSON_SCHEMA_VALIDATION_REPORT(schema,document)

校驗document文檔是否符合schema定義的JSON規則,並返回JSON格式的校驗報告。

如果校驗成功,則返回:{"valid": true}。

如果校驗失敗,則返回的校驗報告中會包含以下內容:

  • valid。校驗失敗則爲false。
  • reason。失敗原因。
  • schema-location。校驗失敗的節點在schema中的位置。
  • document-location。校驗失敗的節點在document中的位置。
  • schema-failed-keyword。包含校驗失敗節點的一段schema的關鍵字。

一個校驗失敗的場景:

mysql> SET @schema = '{
    '>  "id": "http://json-schema.org/geo",
    '> "$schema": "http://json-schema.org/draft-04/schema#",
    '> "description": "A geographical coordinate",
    '> "type": "object",
    '> "properties": {
    '>   "latitude": {
    '>     "type": "number",
    '>     "minimum": -90,
    '>     "maximum": 90
    '>   },
    '>   "longitude": {
    '>     "type": "number",
    '>     "minimum": -180,
    '>     "maximum": 180
    '>   }
    '> },
    '> "required": ["latitude", "longitude"]
    '> }';
Query OK, 0 rows affected (0.00 sec)

mysql> SET @document = '{
    '> "latitude": 63.444697,
    '> "longitude": 310.445118
    '> }';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT JSON_PRETTY(JSON_SCHEMA_VALIDATION_REPORT(@schema, @document));
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| JSON_PRETTY(JSON_SCHEMA_VALIDATION_REPORT(@schema, @document))                                                                                                                                                                                                                        |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| {
  "valid": false,
  "reason": "The JSON document location '#/longitude' failed requirement 'maximum' at JSON Schema location '#/properties/longitude'",
  "schema-location": "#/properties/longitude",
  "document-location": "#/longitude",
  "schema-failed-keyword": "maximum"
} |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

JSON_PRETTY()函數的作用是讓返回的結果格式更好看一些,否則是一行顯示。

 

七,JSON輔助函數

1,JSON_PRETTY(json_val)

格式化JSON值,讓輸出更好看一些。

參數必須是JSON值或者是符合JSON格式的字符串。

舉例:

mysql> SELECT JSON_PRETTY('["a",1,{"key1":
    '>    "value1"},"5",     "77" ,
    '>       {"key2":["value3","valueX",
    '> "valueY"]},"j", "2"   ]');
+-------------------------------------------------------------------------------------------------------------------------------------------------------+
| JSON_PRETTY('["a",1,{"key1":
   "value1"},"5",     "77" ,
      {"key2":["value3","valueX",
"valueY"]},"j", "2"   ]')                                 |
+-------------------------------------------------------------------------------------------------------------------------------------------------------+
| [
  "a",
  1,
  {
    "key1": "value1"
  },
  "5",
  "77",
  {
    "key2": [
      "value3",
      "valueX",
      "valueY"
    ]
  },
  "j",
  "2"
] |
+-------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

 

2,JSON_STORAGE_FREE(json_val)

此函數的功能是,在使用JSON_SET(),JSON_REPLACE(),JSON_REMOVE()函數修改了列值之後,JSON釋放了多少空間。

多次使用這三個函數修改列值,此函數返回值會累加。

不使用這三個函數修改列值時,比如直接用set關鍵字修改列值,則此函數返回0。

只對修改表中存儲JSON值的場景有效,如果用三個函數修改用戶變量,此函數返回值依然是0。

參數是JSON字符串,返回值會是0。

比如:

mysql> select * from test_j;
+----------------------------------------------+
| a                                            |
+----------------------------------------------+
| {"a": 10, "b": "wxyz", "c": "[true, false]"} |
+----------------------------------------------+
1 row in set (0.00 sec)

mysql> update test_j SET a = JSON_SET(a, "$.a", 10, "$.b", "wxyz", "$.c", 1);        
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from test_j;
+--------------------------------+
| a                              |
+--------------------------------+
| {"a": 10, "b": "wxyz", "c": 1} |
+--------------------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_STORAGE_FREE(a) FROM test_j;
+----------------------+
| JSON_STORAGE_FREE(a) |
+----------------------+
|                   14 |
+----------------------+
1 row in set (0.00 sec)

mysql>  update test_j SET a = JSON_SET(a, "$.a", 10, "$.b", "wx", "$.c", 1);   
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> SELECT JSON_STORAGE_FREE(a) FROM test_j;
+----------------------+
| JSON_STORAGE_FREE(a) |
+----------------------+
|                   16 |
+----------------------+
1 row in set (0.00 sec)

mysql> update test_j set a = '{"a": 10, "b": "wx"}';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> SELECT JSON_STORAGE_FREE(a) FROM test_j; 
+----------------------+
| JSON_STORAGE_FREE(a) |
+----------------------+
|                    0 |
+----------------------+
1 row in set (0.00 sec)

mysql> SELECT JSON_STORAGE_FREE('{"a": 10, "b": "wxyz", "c": "1"}');
+-------------------------------------------------------+
| JSON_STORAGE_FREE('{"a": 10, "b": "wxyz", "c": "1"}') |
+-------------------------------------------------------+
|                                                     0 |
+-------------------------------------------------------+
1 row in set (0.00 sec)

 

3,JSON_STORAGE_SIZE(json_val)

此函數返回的是一個JSON值轉換成二進制後佔用的磁盤空間。

如果參數是一個JSON格式的列,則表示此列的JSON值轉換成二進制後佔用的磁盤空間。

如果參數是一個JSON格式的字符串,則表示此字符串代表的JSON值轉換成二進制後會佔用的磁盤空間。

JSON_SET(),JSON_REPLACE(),JSON_REMOVE()三個函數會部分更新JSON值,不會導致此函數的返回值發生變化。直接用set關鍵字修改列值會導致此函數返回值發生變化。

因爲用戶變量不能部分修改,所以當修改用戶變量時,此函數的返回值會立刻變化。

舉例:

mysql> select * from test_j;
+-----------------------------------------------+
| a                                             |
+-----------------------------------------------+
| {"a": 1000, "b": "wxyz", "c": "[1, 3, 5, 7]"} |
+-----------------------------------------------+
1 row in set (0.00 sec)

mysql> select 
    ->   a,
    ->   JSON_STORAGE_SIZE(a) AS Size,
    ->   JSON_STORAGE_FREE(a) AS Free
    -> from test_j;
+-----------------------------------------------+------+------+
| a                                             | Size | Free |
+-----------------------------------------------+------+------+
| {"a": 1000, "b": "wxyz", "c": "[1, 3, 5, 7]"} |   47 |    0 |
+-----------------------------------------------+------+------+
1 row in set (0.00 sec)

mysql> UPDATE test_j SET a = JSON_SET(a, "$.b", "a");        
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select 
    ->   a,
    ->   JSON_STORAGE_SIZE(a) AS Size,
    ->   JSON_STORAGE_FREE(a) AS Free
    -> from test_j;
+--------------------------------------------+------+------+
| a                                          | Size | Free |
+--------------------------------------------+------+------+
| {"a": 1000, "b": "a", "c": "[1, 3, 5, 7]"} |   47 |    3 |
+--------------------------------------------+------+------+
1 row in set (0.00 sec)

mysql> update test_j set a = '{"a": 4.55, "b": "wxyz", "c": "[true, false]"}';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select 
    ->   a,
    ->   JSON_STORAGE_SIZE(a) AS Size,
    ->   JSON_STORAGE_FREE(a) AS Free
    -> from test_j;
+------------------------------------------------+------+------+
| a                                              | Size | Free |
+------------------------------------------------+------+------+
| {"a": 4.55, "b": "wxyz", "c": "[true, false]"} |   56 |    0 |
+------------------------------------------------+------+------+
1 row in set (0.00 sec)

mysql> SET @j = '[100, "sakila", [1, 3, 5], 425.05]';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @j, JSON_STORAGE_SIZE(@j) AS Size;
+------------------------------------+------+
| @j                                 | Size |
+------------------------------------+------+
| [100, "sakila", [1, 3, 5], 425.05] |   45 |
+------------------------------------+------+
1 row in set (0.01 sec)

mysql> SET @j = JSON_SET(@j, '$[1]', "json");
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @j, JSON_STORAGE_SIZE(@j) AS Size;
+----------------------------------+------+
| @j                               | Size |
+----------------------------------+------+
| [100, "json", [1, 3, 5], 425.05] |   43 |
+----------------------------------+------+
1 row in set (0.00 sec)

mysql> SELECT
    ->     JSON_STORAGE_SIZE('[100, "sakila", [1, 3, 5], 425.05]') AS A,
    ->     JSON_STORAGE_SIZE('{"a": 1000, "b": "a", "c": "[1, 3, 5, 7]"}') AS B,
    ->     JSON_STORAGE_SIZE('{"a": 1000, "b": "wxyz", "c": "[1, 3, 5, 7]"}') AS C,
    ->     JSON_STORAGE_SIZE('[100, "json", [[10, 20, 30], 3, 5], 425.05]') AS D;
+----+----+----+----+
| A  | B  | C  | D  |
+----+----+----+----+
| 45 | 44 | 47 | 56 |
+----+----+----+----+
1 row in set (0.00 sec)

 

 

MySQL8.0全部學習筆記:

MySQL8.0新特性學習筆記(一):binlog複製策略優化

MySQL8.0新特性學習筆記(二):窗口函數

MySQL8.0新特性學習筆記(三):直方圖

MySQL8.0新特性學習筆記(四):Hash Join

MySQL8.0新特性學習筆記(五):JSON格式簡介和JSON函數詳解

MySQL8.0新特性學習筆記(六):新特性介紹

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章