轉載阿里巴巴首席技術官 最後發佈於2019-08-08 20:23:56 閱讀數 1402 收藏
此學習文是基於MySQL 8.0寫的
得益於大神朋友的悉心指導解決很多坑,才寫出此文,向大神奉上膝蓋
html
要在MySQL中存儲數據,就必須定義數據庫和表結構(schema),這是一個主要的限制。爲了應對這一點,從MySQL 5.7開始,MySQL支恃了 JavaScript對象表示(JavaScriptObject Notation,JSON) 數據類型。以前,這類數據不是單獨的數據類型,會被存儲爲字符串。新的JSON數據類型提供了自動驗證的JSON文檔以及優化的存儲格式。mysql
JSON文檔以二進制格式存儲,它提供如下功能:sql
對文檔元素的快速讀取訪問。
當服務器再次讀取JSON文檔時,不須要從新解析文本獲取該值。
經過鍵或數組索引直接查找子對象或嵌套值,而不須要讀取文檔中的全部值。
建立一個測試表
數據庫
-
mysql> create table employees.emp_details (
-
-> emp_no int primary key,
-
-> details json
-
-> );
-
Query OK, 0 rows affected (0.17 sec)
-
-
mysql> desc employees.emp_details;
-
+---------+---------+------+-----+---------+-------+
-
| Field | Type | Null | Key | Default | Extra |
-
+---------+---------+------+-----+---------+-------+
-
| emp_no | int( 11) | NO | PRI | NULL | |
-
| details | json | YES | | NULL | |
-
+---------+---------+------+-----+---------+-------+
-
2 rows in set (0.00 sec)
插入JSONjson
-
mysql> insert into employees.emp_details (emp_no, details)
-
-> values (' 1',
-
-> '{ "location":"IN","phone":"+11800000000","email":"abc@example.com","address":{"line1":"abc","line2":"xyz street","city":"Bangalore","pin":"560103"}}'
-
-> );
-
Query OK, 1 row affected (0.13 sec)
-
-
mysql> select emp_no, details from employees.emp_details;
-
+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
-
| emp_no | details |
-
+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
-
| 1 | {"email": "abc@example.com", "phone": "+11800000000", "address": {"pin": "560103", "city": "Bangalore", "line1": "abc", "line2": "xyz street"}, "location": "IN"} |
-
+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
-
1 row in set (0.00 sec)
檢索JSON
可使用->和->>運算符檢索JSON列的字段:
數組
-
mysql> select emp_no, details -> '$.address.pin' pin
-
-> from employees.emp_details;
-
+--------+----------+
-
| emp_no | pin |
-
+--------+----------+
-
| 1 | "560103" |
-
+--------+----------+
-
1 row in set (0.00 sec)
若是不用引號檢索數據,可使用->> 運算符(推薦此方式)服務器
-
mysql> select emp_no, details ->> '$.address.pin' pin
-
-> from employees.emp_details;
-
+--------+--------+
-
| emp_no | pin |
-
+--------+--------+
-
| 1 | 560103 |
-
+--------+--------+
-
1 row in set (0.00 sec)
JSON函數
MySQL提供了許多處理JSON數據的函數,讓咱們看看最經常使用的幾種函數。
函數
1. 優雅瀏覽
想要以優雅的格式顯示JSON值,請使用JSON_PRETTY()函數
學習
-
mysql> select emp_no, json_pretty(details)
-
-> from employees.emp_details\ G
-
*************************** 1. row ***************************
-
emp_no: 1
-
json_pretty(details): {
-
"email": "abc@example.com",
-
"phone": "+11800000000",
-
"address": {
-
"pin": "560103",
-
"city": "Bangalore",
-
"line1": "abc",
-
"line2": "xyz street"
-
},
-
"location": "IN"
-
}
-
1 row in set (0.00 sec)
2. 查找
能夠在WHERE子句中使用col ->> path運算符來引用JSON的某一列
測試
-
mysql> select emp_no, details
-
-> from employees.emp_details
-
-> where details ->> '$.address.pin' = "560103";
-
+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
-
| emp_no | details |
-
+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
-
| 1 | {"email": "abc@example.com", "phone": "+11800000000", "address": {"pin": "560103", "city": "Bangalore", "line1": "abc", "line2": "xyz street"}, "location": "IN"} |
-
+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
-
1 row in set (0.00 sec)
也可使用JSON_CONTAINS函數查詢數據。若是找到了數據,則返回1,不然返回0
-
mysql> select json_contains(details ->> '$.address.pin', "560103")
-
-> from employees.emp_details;
-
+-----------------------------------------------------+
-
| json_contains(details ->> '$.address.pin', "560103") |
-
+-----------------------------------------------------+
-
| 1 |
-
+-----------------------------------------------------+
-
1 row in set (0.00 sec)
如何查詢一個key?使用JSON_CONTAINS_PATH函數檢查address. line1是否存在
-
mysql> select json_contains_path(details, 'one', "$.address.line1")
-
-> from employees.emp_details;
-
+-------------------------------------------------------+
-
| json_contains_path(details, 'one', "$.address.line1") |
-
+-------------------------------------------------------+
-
| 1 |
-
+-------------------------------------------------------+
-
1 row in set (0.00 sec)
one表示至少應該存在一個鍵,檢查address.line1或者address.line2是否存在
-
mysql> select json_contains_path(details, 'one', "$.address.line1", "$.address.line2")
-
-> from employees.emp_details;
-
+--------------------------------------------------------------------------+
-
| json_contains_path(details, 'one', "$.address.line1", "$.address.line2") |
-
+--------------------------------------------------------------------------+
-
| 1 |
-
+--------------------------------------------------------------------------+
-
1 row in set (0.00 sec)
若是要檢查address.line1或者address.line5是否同時存在,可使用all,而不是one
-
mysql> select json_contains_path(details, 'all', "$.address.line1", "$.address.line5")
-
-> from employees.emp_details;
-
+--------------------------------------------------------------------------+
-
| json_contains_path(details, 'all', "$.address.line1", "$.address.line5") |
-
+--------------------------------------------------------------------------+
-
| 0 |
-
+--------------------------------------------------------------------------+
-
1 row in set (0.00 sec)
3. 修改
可使用三種不一樣的函數來修改數據:JSON_SET()、JSON_INSERT()和JSON _REPLACE()。 在MySQL 8以前的版本中,咱們還須要對整個列進行完整的更新,這並非最佳的方法。
3.1. JSON_SET() 替換現有值並添加不存在的值
-
mysql> update employees.emp_details
-
-> set details = json_set(details, "$.address.pin", "560100", "$.nickname","kai")
-
-> where emp_no = 1;
-
Query OK, 1 row affected (0.01 sec)
-
Rows matched: 1 Changed: 1 Warnings: 0
-
-
mysql> select emp_no, json_pretty(details)
-
-> from employees.emp_details\ G
-
*************************** 1. row ***************************
-
emp_no: 1
-
json_pretty(details): {
-
"email": "abc@example.com",
-
"phone": "+11800000000",
-
"address": {
-
"pin": "560100",
-
"city": "Bangalore",
-
"line1": "abc",
-
"line2": "xyz street"
-
},
-
"location": "IN",
-
"nickname": "kai"
-
}
-
1 row in set (0.00 sec)
3.2. JSON_INSERT() 插入值,但不替換現有值
在這種狀況下,$.address.pin不會被更新,只會添加一個新的字段$.address.line4
-
mysql> update employees.emp_details
-
-> set details = json_insert(details, "$.address.pin", "560132", "$.address.line4","A Wing")
-
-> where emp_no = 1;
-
Query OK, 1 row affected (0.01 sec)
-
Rows matched: 1 Changed: 1 Warnings: 0
-
-
mysql> select emp_no, json_pretty(details)
-
-> from employees.emp_details\ G
-
*************************** 1. row ***************************
-
emp_no: 1
-
json_pretty(details): {
-
"email": "abc@example.com",
-
"phone": "+11800000000",
-
"address": {
-
"pin": "560100",
-
"city": "Bangalore",
-
"line1": "abc",
-
"line2": "xyz street",
-
"line4": "A Wing"
-
},
-
"location": "IN",
-
"nickname": "kai"
-
}
-
1 row in set (0.01 sec)
3.3. JSON_REPLACE()
僅替換現有值
在這種狀況下,$.address.line5不會被添加, 只有$.address.pin會被更新
-
mysql> update employees.emp_details
-
-> set details = json_replace(details, "$.address.pin", "560132", "$.address.line5","Landmark")
-
-> where emp_no = 1;
-
Query OK, 1 row affected (0.00 sec)
-
Rows matched: 1 Changed: 1 Warnings: 0
-
-
mysql> select emp_no, json_pretty(details)
-
-> from employees.emp_details\ G
-
*************************** 1. row ***************************
-
emp_no: 1
-
json_pretty(details): {
-
"email": "abc@example.com",
-
"phone": "+11800000000",
-
"address": {
-
"pin": "560132",
-
"city": "Bangalore",
-
"line1": "abc",
-
"line2": "xyz street",
-
"line4": "A Wing"
-
},
-
"location": "IN",
-
"nickname": "kai"
-
}
-
1 row in set (0.00 sec)
4. 刪除 JSON_REMOVE能從JSON文檔中刪除數據
-
mysql> update employees.emp_details
-
-> set details = json_remove(details, "$.address.line4")
-
-> where emp_no = 1;
-
Query OK, 1 row affected (0.01 sec)
-
Rows matched: 1 Changed: 1 Warnings: 0
-
-
mysql> select emp_no, json_pretty(details)
-
-> from employees.emp_details\ G
-
*************************** 1. row ***************************
-
emp_no: 1
-
json_pretty(details): {
-
"email": "abc@example.com",
-
"phone": "+11800000000",
-
"address": {
-
"pin": "560132",
-
"city": "Bangalore",
-
"line1": "abc",
-
"line2": "xyz street"
-
},
-
"location": "IN",
-
"nickname": "kai"
-
}
-
1 row in set (0.00 sec)
5. 其餘函數
JSON_KEYS():獲取JSON文檔中的全部鍵
-
mysql> select json_keys(details),json_keys(details ->> "$.address")
-
-> from employees.emp_details
-
-> where emp_no= 1;
-
+-------------------------------------------------------+------------------------------------+
-
| json_keys(details) | json_keys(details ->> "$.address") |
-
+-------------------------------------------------------+------------------------------------+
-
| [ "email", "phone", "address", "location", "nickname"] | ["pin", "city", "line1", "line2"] |
-
+-------------------------------------------------------+------------------------------------+
-
1 row in set (0.00 sec)
JSON_LENGTH():給出JSON文檔中的元素數
-
mysql> select json_length(details), json_length(details ->> "$.address")
-
-> from employees.emp_details
-
-> where emp_no= 1;
-
+----------------------+--------------------------------------+
-
| json_length(details) | json_length(details ->> "$.address") |
-
+----------------------+--------------------------------------+
-
| 5 | 4 |
-
+----------------------+--------------------------------------+
-
1 row in set (0.00 sec)
延伸閱讀: https://dev.mysql.com/doc/refman/8.0/en/json-function-reference.html