oracle mysql 5.7.8 以後增長了對json數據格式的函數處理,可更加靈活的在數據庫中操做json數據,如可變屬性、自定義表單等等都使用使用該方式解決。mysql
在建立表時,能夠使用「GENERATED ALWAYS AS」 與json中的某個字段關聯,並建立虛擬字段使json字符串也能夠添加索引。sql
-- 建立測試json表 CREATE TABLE `test_json` ( `$json` json NOT NULL, `userid` varchar(50) COLLATE utf8mb4_unicode_ci GENERATED ALWAYS AS (json_unquote(json_extract(`$json`,_utf8mb4'$."userid"'))) VIRTUAL, `id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL, `$createTime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, `$updateTime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `name` varchar(60) GENERATED ALWAYS AS ((json_extract(`$json`,_utf8mb4'$."name"') = TRUE)) VIRTUAL, PRIMARY KEY (`id`), KEY `by_userid` (`userid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; SET FOREIGN_KEY_CHECKS = 1;
建立json數據庫
json_array(val1,val2,val3...) | 建立json數組 |
json_object(key1,value1,key2,value2...) | 建立json對象 |
json_quote | 將json轉成json字符串類型 |
插入json數據json
-- 方式1 :直接插入json字符串 insert into test_json (id,`$json`) values(1,'{"userid":"1","name":"test name","sex":"男"}'); -- 方式2 :使用json_object insert into test_json (id,`$json`) values(2,json_object("userid","2","name","test name2","sex","男")); -- 方式3 :組合使用 insert into test_json (id,`$json`) values(3,json_object("userid","3","name","name3","sex","女","item",json_array("item1","item2","item3")));
查詢json數組
json_contains(json_doc,val[,path]) | 判斷是否包含某個json值 |
json_contains_path(json_doc,one_or_all,path[,path]...) | 判斷是否有某個路徑 |
json_extract(json_doc,path[,path]) | 提取json值 |
column->path json_extract | 簡潔寫法5.7.9開始支持 |
column->>path json_unquote(column -> path) | 簡潔寫法5.7.13開始支持至關於oracle JSON_UNQUOTE(JSON_EXTRACT())app |
json_keys(json_doc[,path]) | 提取json中的鍵值結果爲json數組 |
json_search(json_doc, one_or_all, search_str[,escape_char[,path]...]) | 按給定字符串關鍵字搜索json,返回匹配的路徑 |
搜索數組下的多個屬性時可以使用通配符「*」,如獲取數組下對象的某屬性$.item[*].name函數
-- 判斷是否包含某個json值 -- 方式1 select json_contains(`$json`,'{"name":"test name2"}') from test_json; -- 方式2 (請注意第二個參數,帶雙引號,官網案例是number類型) select json_contains(`$json`,'"name3"','$.name') from test_json; -- 判斷json是否指定路徑,one至少存在一條路徑,all存在全部路徑 select json_contains_path($json,'one','$.item') from test_json; -- 獲取json值 -- 方式1 select json_extract(`$json`,'$.item') from test_json; -- 方式2 簡潔寫法 select `$json` -> '$.item' from test_json; -- 方式3 簡潔寫法,並取消字符串,可用於select\where\having子句 select `$json` ->> '$.name' from test_json; -- 獲取json中的key數組 select json_keys($json) from test_json; -- 獲取json中指定value的json_path select json_search($json,'one','item2') from test_json; -- 可以使用通配符 select json_search($json,'one','item%') from test_json; select json_search($json,'all','2') from test_json;
修改json性能
json_append (廢棄) | 廢棄,MySQL 5.7.9開始更名爲json_array_append |
json_array_append(json_doc,path,val[,path,val]...) | 末尾添加數組元素,若是原有值是數值或json對 象,則轉成數組後,再添加元素 |
json_array_insert(json_doc,path,val[,path,val]...) | 插入數組元素 |
json_insert(json_doc,path,val[,path,val]...) | 插入值(插入新值,但不替換已經存在的舊值) |
json_merge(json_doc,json_doc[,json_doc]...) | 合併json數組或對象 |
json_remove(json_doc,path[,path]...) | 刪除json數據 |
json_replace(json_doc,path,val[,path,val]...) | 替換值(只替換已經存在的舊值) |
json_set(json_doc,path,val[,path,val]) | 設置值(替換舊值,並插入不存在的新值) |
json_unquote(val) | 去除json字符串的引號,將值轉成string類型 |
CAST('jsonString' as json) | 可將json字符串轉爲json對象格式 |
-- 修改json -- 只會給有item屬性的json添加 select json_array_append(`$json`,'$.item','new item') from test_json ; -- 會將對象轉爲數組 select json_array_append(`$json`,'$.name','new item') from test_json ; -- 向數組指定位置插入,指定的json path必須是數組類型 select json_array_insert(`$json`,'$.item[10]','new item') from test_json ; -- 添加新屬性,若是沒有新屬性會增長 select json_insert(`$json`,'$.address','北京') from test_json ; -- 修改原屬性,若是沒有屬性會增長,若是有則不處理 select json_insert(`$json`,'$.name','新名字') from test_json ; -- 也可向數組中插入 select json_insert(`$json`,'$.item[10]','new item') from test_json ; -- 合併,根據屬性進行合併,若有相同屬性轉爲數組 select json_merge(`$json`,`$json`) from test_json ; -- 添加新屬性,合併數組 select json_merge(`$json`,'{"company":"companyName","address":"address","item":["newItem"]}') from test_json ; -- 刪除指定路徑屬性或數組值 select json_remove(`$json`,'$.item','$.sex') from test_json ; select json_remove(`$json`,'$.item[0]','$.sex') from test_json ; -- 替換屬性值 select json_replace(`$json`,'$.sex','男') from test_json ; -- 替換沒有的屬性不作任何操做 select json_replace(`$json`,'$.address','替換不存在的地址屬性','$.item[20]','4444') from test_json ; -- 有的屬性作替換值,沒有的作添加 select json_set(`$json`,'$.sex','男','$.address','替換不存在的地址屬性','$.item[20]','4444') from test_json ; -- 原始獲取json會帶引號 select `$json` -> '$.name' from test_json ; -- 可去除雙引號 select json_unquote(`$json` -> '$.name') from test_json ;
返回json屬性測試
json_depth(json_doc) | 返回json文檔的最大深度 |
json_length(json_doc[,path]) | 返回json文檔的長度 |
json_type(json_val) | 返回json值得類型 |
json_valid()val | 判斷是否爲合法json文檔 |
-- json屬性最大深度 select json_depth(`$json`) from test_json ; -- json對象則是屬性數,數組則是數組長度 select json_length(`$json`) from test_json ; -- 判斷數據類型 select json_type(`$json`) from test_json ; select json_type(`$json` -> '$.name') from test_json ; select json_type(`$json` -> '$.item') from test_json ;
json類型 | |
ARRAY | JSON數組 |
BOOLEAN | JSON true和false字符串 |
NULL | JSON NULL字符串 |
數字類型 | |
INTEGER | MySQL中 TINYINT, SMALLINT, MEDIUMINT, INT 和 BIGINT |
DOUBLE | MySQL中 DOUBLE FLOAT |
DECIMAL | DECIMAL 和 NUMERIC |
時間類型 | |
DATETIME | MySQL中 DATETIME 和 TIMESTAMP |
DATE | MySQL中 DATE |
TIME | MySQL中 TIME |
字符串類型 | |
STRING | MySQL字符串: CHAR, VARCHAR, TEXT, ENUM, 和 SET |
二進制 | |
BLOB | MySQL 二進制: BINARY, VARBINARY, BLOB |
BIT | MySQL中 BIT |
其餘 | |
OPAQUE | (raw bits) |
引用:https://blog.csdn.net/qian_xiaoqian/article/details/53128170
在處理JSON時,MySQL使用的utf8mb4字符集,utf8mb4是utf8和ascii的超集。因爲歷史緣由,這裏utf8並不是是咱們常說的UTF-8 Unicode變長編碼方案,而是MySQL自身定義的utf8編碼方案,最長爲三個字節。具體區別非本文重點,請你們自行Google瞭解。
MySQL在內存中是以DOM的形式表示JSON文檔,並且在MySQL解析某個具體的路徑表達式時,只須要反序列化和解析路徑上的對象,並且速度極快。要弄清楚MySQL是如何作到這些的,咱們就須要瞭解JSON在硬盤上的存儲結構。有個有趣的點是,JSON對象是BLOB的子類,在其基礎上作了特化。
使用示意圖更清晰的展現它的結構:
JSON文檔自己是層次化的結構,於是MySQL對JSON存儲也是層次化的。對於每一級對象,存儲的最前面爲存放當前對象的元素個數,以及總體佔的大小。須要注意的是: