日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

MySQL数据库的JSON数据类型详解

發布時間:2023/12/20 数据库 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL数据库的JSON数据类型详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • JSON 數據類型意義
  • 存儲JSON串
  • 修改JSON串中指定字段的值
  • 查詢 JSON 串中的數據
    • 查詢 JSON 串中指定字段的值
      • 特殊語法
    • 精確查詢
    • 嵌套精確查詢
    • 模糊查詢
  • 優化 JSON 查詢
  • 處理 JSON 數據的常用函數
    • JSON_CONTAINS_PATH
    • JSON_PRETTY
  • 總結
  • 參考資料

JSON 數據類型意義

其實,沒有JSON數據類型的支持,我們一樣可以通過varchar類型或者text等類型來保存這一格式的數據,但是,為什么還要專門增加這一數據格式的支持呢?其中肯定有較varchar或者text來存儲此類型更優越的地方。

1.保證了 JSON 數據類型的強校驗,JSON 數據列會自動校驗存入此列的內容是否符合 JSON 格式,非正常格式則報錯,而 varchar 類型和 text 等類型本身是不存在這種機制的。
2.MySQL 同時提供了一組操作 JSON 類型數據的內置函數。
3.更優化的存儲格式,存儲在 JSON 列中的 JSON 數據會被轉成內部特定的存儲格式,允許快速讀取。
4.基于 JSON 格式的特征,支持修改指定的字段值。

存儲JSON串

insert into commodity(commodity_id,title,current_selling_price,attributes) values (9,'小米手機',2000,'{"specValueId":"3845862150911746064","specValue":"深紅色","specValueType":"紅色系","specValueTypeId":"3845862150911746056","specId":"3845862150911746061","specName":"xx顏色","specType":"顏色","extdata1":"rgba(255, 9, 9, 1)","extdata2":"http://localhost:8080/123.png"}');

這里需要提醒的是:
JSON 類型的列存儲的數據要么是 NULL,要么必須是 JSON 格式數據,否則會報錯。
JSON 數據類型默認值只能是 NULL。

修改JSON串中指定字段的值

可以使用兩個內置函數來修改JSON串中指定字段的值,示例如下:

# 將列attributes中的json串中的字段specValue的值設置為‘綠色’ update commodity set attributes = JSON_SET(attributes,'$.specValue','綠色') where title like '%手機'; # 將列attributes中的json串中的字段specValue的值替換為‘yellow’ update commodity set attributes = JSON_REPLACE(attributes,'$.specValue','yellow') where title like '%手機';

查詢 JSON 串中的數據

查詢 JSON 串中指定字段的值

select JSON_EXTRACT(attributes,'$.specValue') from commodity where commodity_id = 9;

這里要特別注意了,讀取json串中指定字段的值,如果該值是字符串則會把雙引號也讀取出來,可以使用函數 JSON_UNQUOTE() 去掉雙引號:

select json_unquote(JSON_EXTRACT(attributes,'$.specValue')) from commodity where commodity_id = 9;

特殊語法

查詢列 attributes 中的 json 串中的字段 specValue 的值,可以使用下面兩種查詢語句:

select attributes->>'$.specValue' from commodity;

或者

select attributes->'$.specValue' from commodity;

精確查詢

假設有個名為 player 的表,有個名為 remarks 的 JSON 類型的列,存儲的數據格式如下:

{"name":"lisi","age":39,"address":{"city":"rizhao","region":"lanshan"}}

查詢 remarks 列中的json串的name字段的值為“zhangsan”的所有記錄:

SELECT * FROM `player` WHERE JSON_EXTRACT(`Remarks`, '$.name') = 'zhangsan';

或者

SELECT * FROM `player` WHERE JSON_CONTAINS(Remarks,JSON_OBJECT('name','zhangsan'));

或者

select * from player where json_contains(remarks,'"zhangsan"','$.name');

嵌套精確查詢

查詢用戶居住城市是日照的所有記錄:

SELECT * FROM `player` WHERE JSON_EXTRACT(`Remarks`, '$.address.city') = 'rizhao';

模糊查詢

查詢列 remarks 中的json串中的字段name的值中包含“zhangsan”的所有記錄:

SELECT * FROM `player` WHERE JSON_EXTRACT(`Remarks`, '$.name') LIKE '%zhangsan%';

查詢列 remarks 中的 json 串中的字段 age 的值大于等于 25 的所有記錄:

SELECT * FROM `player` WHERE JSON_EXTRACT(`Remarks`, '$.age') >= 25;

優化 JSON 查詢

找出顏色是“綠色”的商品:

select * from commodity where JSON_EXTRACT(attributes,'$.specValue') = 'yellow';

查看執行計劃:

explain select * from commodity where JSON_EXTRACT(attributes,'$.specValue') = 'yellow';


從執行計劃可以看到,查詢類型是全表掃描,這樣的效率是很低的,那么如何優化呢?

按照過往的思路,我們只要設計合理的索引就能避免全表掃描,但是 JSON 列不能創建索引,官方給出的方法是:基于JSON 創建一個生成列(Generated Column),然后基于生成列創建索引,從而達到對 JSON 類型列加索引的效果。

生成列的值在插入數據時不需要設置,MySQL 會根據生成列關聯的表達式自動計算填充。

我們分三步進行演示。
第一步,創建生成列:

alter table commodity add column v_spec_value varchar(15) as (attributes->'$.specValue') after attributes;

生成列 v_spec_value 的值根據表達式 attributes->'$.specValue' 自動計算填充。

第二步,為 v_spec_value 創建索引:

alter table commodity add index idx_spec_value (v_spec_value);

第三步,使用索引字段來查詢:

select * from commodity where v_spec_value = '"yellow"';

在查看執行計劃:

explain select * from commodity where v_spec_value = '"yellow"';

有個疑問:根據表達式獲取JSON串中指定字段值,如果是字符串類型的,會把雙引號也獲取到,導致存儲時也會將雙引號一起存進去,這個問題如何解決呢?

處理 JSON 數據的常用函數

JSON_CONTAINS_PATH

判斷 JSON 串中是否有指定的字段。

查詢列attributes 中的 json 串中含有字段 specValue的記錄數量:

SELECT count(*), JSON_CONTAINS_PATH(attributes, 'all', '$.specValue') cp FROM commodity GROUP BY cp;

查詢結果如下:

mysql> SET @j = '{"a": 1, "b": 2, "c": {"d": 4}}'; mysql> SELECT JSON_CONTAINS_PATH(@j, 'one', '$.a', '$.e'); -- 指定參數one,表示只要json串中含有至少一個指定字段,則返回1,否則返回0 +---------------------------------------------+ | JSON_CONTAINS_PATH(@j, 'one', '$.a', '$.e') | +---------------------------------------------+ | 1 | +---------------------------------------------+ mysql> SELECT JSON_CONTAINS_PATH(@j, 'all', '$.a', '$.e'); -- 指定參數all,表示json串中必須含有全部指定的字段才會返回1,否則返回0 +---------------------------------------------+ | JSON_CONTAINS_PATH(@j, 'all', '$.a', '$.e') | +---------------------------------------------+ | 0 | +---------------------------------------------+ mysql> SELECT JSON_CONTAINS_PATH(@j, 'one', '$.c.d'); +----------------------------------------+ | JSON_CONTAINS_PATH(@j, 'one', '$.c.d') | +----------------------------------------+ | 1 | +----------------------------------------+ mysql> SELECT JSON_CONTAINS_PATH(@j, 'one', '$.a.d'); +----------------------------------------+ | JSON_CONTAINS_PATH(@j, 'one', '$.a.d') | +----------------------------------------+ | 0 | +----------------------------------------+

JSON_PRETTY

返回格式化的 json 數據:

select json_pretty(attributes) from commodity;

格式化后,顯示成這樣:

{"specId": "3845862150911746061","extdata1": "rgba(255, 9, 9, 1)","extdata2": "http://localhost:8080/123.png","specName": "xx顏色","specType": "顏色","specValue": "yellow","specValueId": "3845862150911746064","specValueType": "紅色系","specValueTypeId": "3845862150911746056" }

總結

JSON 類型是 MySQL 5.7 版本新增的數據類型,用好 JSON 數據類型可以有效解決很多業務中實際問題。最后,我總結下今天的重點內容: 使用 JSON 數據類型,推薦用 MySQL 8.0.17 以上的版本,性能更好,同時也支持 Multi-Valued Indexes。

1.JSON 數據類型的好處是無須預先定義列,數據本身就具有很好的描述性;
2.不要將有明顯關系型的數據用 JSON 存儲,如用戶余額、用戶姓名、用戶身份證等,這些都是每個用戶必須包含的數據;
3.JSON 數據類型推薦用于存儲不經常更新的靜態數據。

參考資料

1.https://dev.mysql.com/doc/refman/5.7/en/json-functions.html
2.https://zhuanlan.zhihu.com/p/31823258
3.https://dasini.net/blog/2018/07/23/30-mins-with-mysql-json-functions/

總結

以上是生活随笔為你收集整理的MySQL数据库的JSON数据类型详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。