MYSQL 直接解析json

MySQL 5.7版本以後支持json格式的字段類型定義、存儲和使用,最近做BI開發,開發把所需數據用JSON的形式存儲在字段中,本次記錄下MySQL解析JSON。

 

環境:MySQL 8.0

角色:root

 

參考:

https://dev.mysql.com/doc/refman/8.0/en/json.html

 

一般來說,主要是提取json字段的值,所以update就不寫了,提取select json使用的參數是:

 JSON_EXTRACT

 

JSON_EXTRACT參數使用方式是:JSON_EXTRACT(json串,'$.key'),select後得到的是key值對應的value;

那麼,如何解釋$

$,指得是json串,這裏的json串,是$之前的變量;例如:

JSON_EXTRACT('{1:0,2:0}','$.key')這裏$.key的$指的是他前面的{1:0,2:0}

JSON_EXTRACT(JSON_EXTRACT('{1:0,2:0}','$.1'),'$.key')

這裏$.key的$指的是他前面的JSON_EXTRACT('{1:0,2:0}','$.1'),

 

如果有多層嵌套的json,JSON_EXTRACT提取出來的子層級結果也是json屬性的列表,JSON_EXTRACT可以層層套用;

 

MySQL EXTRACT解析出的json結果是一個list集合,官方的說法是array,由於操作方式和python的list很相似,同樣就帶有了list的操作方式,就如其他語言一樣,list可以指定key值獲得對應的value,可以循環,可以獲得length,可以遍歷;

MySQL中json解析出的list一樣的有相關屬性和操作;

由此,再回過頭看JSON_EXTRACT('{1:0,2:0}','$.key')

這裏的意義是:解析json串{1:0,2:0},得到list = [1:0,2:0],獲取list中的key值對應的value

所以select JSON_EXTRACT('{1:0,2:0}','$.1')得到的結果是[0]

爲什麼是[0],而不是0

因爲MySQL解析list的key是list,得到的結果value也會是list屬性,

 

到這裏又得到新的靈感,既然解析的key是list屬性,那麼能不能指定key的index?

當然可以,比如有個這樣的json:

{a:[1:0,2:0],b:[1:0,2:0]}

那麼解析select JSON_EXTRACT({a:[1:0,2:0],b:[1:0,2:0]},'$[0]') 會得到[a:[1:0,2:0]]

由此,可以反推json 的index值select JSON_EXTRACT(json,'$[index]')

而select JSON_EXTRACT(json,'$[index].key')則是得到index下標的list中尋找對應的key值

值得注意的是這裏的key只會在list同層中尋找,如果$[index]得到的list還包含多層json或者list,$[index].key並不會得到其他層級的value

如果不確定key在哪個index,那該怎麼辦呢?

sql中一樣存在遍歷,這個符號就是 * 

$[*]就是遍歷list

$[*].key 則是遍歷list中所有的key值並以list的形式反饋回value;當然這裏的遍歷也是同層級的遍歷,如果有子層級,並不會遍歷子層;但這並不妨礙大多數數據庫解析json的使用;

 

所以,如果MySQL要對json進行數據處理,不用存過的形式下,建議:

1、明確數據結構,明確所需數據所在層級

2、明確層級數據定義,不要有的有,有的沒有

 

如果出現json存儲亂存的,值不確定的,層級有變化的,還要從json中提出數據讓數據庫出報表,作爲一名DBA,我肯定會直接踢回去的,本來數據庫就應該存定義好的最小維度,這種破玩意就是程序架構腦袋有si纔會做出這樣的定義,一點也不考慮數據後期維護,如果定義混亂,json_set也不一定能很好的更新維護值。今天接到一個sb的需求,記一記吐槽一下,以後這種需求表結構定義一定要通通打回去。

 

最後,sql範例:

SELECT
	cp.contents,
	replace(replace(replace( JSON_EXTRACT ( JSON_EXTRACT ( cp.contents, "$.comIds" ), '$[*].groupId' ),'"',''),'[',''),']','') ,
	replace(replace(replace( JSON_EXTRACT ( JSON_EXTRACT ( cp.contents, "$.comIds" ), '$[*].groupName' ),'"',''),'[',''),']','') ,
replace(replace(replace(JSON_EXTRACT(JSON_EXTRACT ( JSON_EXTRACT ( cp.contents, "$.comIds" ),"$[*].comIds"),'$[*][*].comid'),'"',''),'[',''),']','') 
FROM
	db_giftcard.t_coupon_assets ca
	LEFT JOIN db_giftcard.t_coupon_product cp ON ca.coupProdId = cp.id

 

 

所以,小結下,要層層遍歷,用$[*][*]

 

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