Mysql如何對json數(shù)據(jù)進行查詢及修改
對json數(shù)據(jù)進行查詢及修改
- 使用 字段->'$.json屬性' 進行查詢條件
- 使用 json_extract 函數(shù)查詢,json_extract(字段, "$.json屬性")
- 根據(jù)json數(shù)組查詢,用 JSON_CONTAINS(字段, JSON_OBJECT('json屬性', "內(nèi)容")) : [{}]查詢這種形式的json數(shù)組
- MySQL5.7以上支持JSON的操作,以及增加了JSON存儲類型
- 一般數(shù)據(jù)庫存儲JSON類型的數(shù)據(jù)會用JSON類型或者TEXT類型
幾個相關函數(shù)
示例
我這里沒有創(chuàng)建json的字段格式,而是使用了text存儲json 。
注意:用JSON類型的話1)JSON列存儲的必須是JSON格式數(shù)據(jù),否則會報錯。2)JSON數(shù)據(jù)類型是沒有默認值的。
插入json格式的數(shù)據(jù)到這一列中:
{"age": "28", "pwd": "lisi", "name": "李四"}
查詢
1、
select * from `offcn_off_main` where json_extract(json_field,"$.name") = '李四'
2、
select * from `offcn_off_main` where json_field->'$.name' = '李四'?
使用explain可以查看到無法使用索引。
所以需要修改:
mysql原生并不支持json列中的屬性索引,但是我們可以通過mysql的虛擬列間接的為json中的某些屬性創(chuàng)建索引,原理就是為json中的屬性創(chuàng)建虛擬列,然后通過給虛擬列建立索引,從而間接的給屬性創(chuàng)建了索引。
在MySQL 5.7中,支持兩種Generated Column,即Virtual Generated Column和Stored Generated Column,前者只將Generated Column保存在數(shù)據(jù)字典中(表的元數(shù)據(jù)),并不會將這一列數(shù)據(jù)持久化到磁盤上;后者會將Generated Column持久化到磁盤上,而不是每次讀取的時候計算所得。很明顯,后者存放了可以通過已有數(shù)據(jù)計算而得的數(shù)據(jù),需要更多的磁盤空間,與Virtual Column相比并沒有優(yōu)勢----(其實我覺得還是有優(yōu)勢畢竟會少一些查詢計算)
因此,MySQL 5.7中,不指定Generated Column的類型,默認是Virtual Column。
如果需要Stored Generated Golumn的話,可能在Virtual Generated Column上建立索引更加合適,一般情況下,都使用Virtual Generated Column,這也是MySQL默認的方式。
格式如下:
fieldname <type> [ GENERATED ALWAYS ] AS ( <expression> ) [ VIRTUAL|STORED ] [ UNIQUE [KEY] ] [ [PRIMARY] KEY ] [ NOT NULL ] [ COMMENT <text> ]
所以我這里:
ALTER TABLE 'off_main' `names_virtual` VARCHAR(20) GENERATED ALWAYS AS (`json_field` ->> '$.name') not null;
Note: 利用操作符-» 來引用JSON字段中的KEY。在本例中字段names_virtual為虛擬字段,我把它定義成不可以為空。在實際的工作中,一定要集合具體的情況來定。因為JSON本身是一種弱結構的數(shù)據(jù)對象。也就是說的它的結構不是固定不變的。
給虛擬字段增加索引:
CREATE INDEX `names` ON `off_main`(`names_virtual`);
注意如果虛擬字段并不是創(chuàng)建表是添加的,而是后面加的,增加索引時如果有的行中虛擬字段為null,但是又設置了它不能為null,那么索引無法創(chuàng)建成功,提示column can not be null.
增加索引后 explain看下即可看到用到了索引,并且虛擬字段的值會隨著json字段的屬性修改而自動變化。
來看看修改
update off_main set json_field = json_set(json_field,'$.phone', '132') WHERE id = 45 //同時修改多個 UPDATE offcn_off_main set json_field = json_set(json_field,'$.name',456,'$.age','bbb') WHERE id = 45
json_set() 方法存在的則會覆蓋,不存在的會添加。
刪除
UPDATE offcn_off_main set json_field = json_remove(json_field,'$.pwd','$.phone') WHERE id = 45
插入
UPDATE offcn_off_main set json_field = json_insert(json_field,'$.pwd','111') WHERE id = 45
insert與update不同之處在于insert不存在的會增加,存在的不會覆蓋
Mysql處理json數(shù)據(jù)
1.如果數(shù)據(jù)量小的話,將json數(shù)據(jù)直接復制到mysql的json字段中,如果數(shù)據(jù)過大可以通過java等后臺形式對json數(shù)據(jù)解析,然后寫入數(shù)據(jù)庫中。
查詢操作
select *,json->'$.features[0].geometry.rings' as rings from JSON;
從一張表讀取一部分數(shù)據(jù)存入另一張表中(一條數(shù)據(jù))
insert into DT_village(name, border) SELECT ? json->'$.features[0].attributes.CJQYMC',json->'$.features[0].geometry.rings' from JSON;
讀取json數(shù)據(jù)并寫入數(shù)據(jù)庫(此時使用的是定義函數(shù)的形式來執(zhí)行方法,可以定義便量)
#清空數(shù)據(jù)庫 TRUNCATE table DT_village; #定義存儲過程 delimiter // DROP PROCEDURE IF EXISTS insert_test_val; ##num_limit 要插入數(shù)據(jù)的數(shù)量,rand_limit 最大隨機的數(shù)值 CREATE PROCEDURE insert_test_val() BEGIN DECLARE i int default 0; DECLARE a,b varchar(5000); WHILE i<10 do set a=CONCAT('$.features[',i,'].attributes.CJQYMC'); set b=CONCAT('$.features[',i,'].geometry.rings'); insert into DT_village(name, border) select #json->'$.features[0].attributes.CJQYMC',json->'$.features[0].geometry.rings' # (json->a),(json->b) json_extract(json,a),json_extract(json,b) from JSON; set i = i + 1; END WHILE; END // #調(diào)用存儲過程 call insert_test_val();
調(diào)用游標的方式獲取jsosn數(shù)據(jù)中的一行,并執(zhí)行插入操作
delimiter // drop procedure if exists StatisticStore; CREATE PROCEDURE StatisticStore() BEGIN #創(chuàng)建接收游標數(shù)據(jù)的變量 declare j json;#存儲json數(shù)據(jù) DECLARE i int default 0; #創(chuàng)建總數(shù)變量,記錄執(zhí)行次數(shù),控制循環(huán) DECLARE a,b,c varchar(5000);#定義json數(shù)組中的某個數(shù)據(jù)的鍵值 #創(chuàng)建結束標志變量 declare done int default false; #創(chuàng)建游標 declare cur cursor for select json from JSON where name = '1'; #指定游標循環(huán)結束時的返回值 declare continue HANDLER for not found set done = true; #設置初始值 set a=CONCAT('$.features[',i,'].attributes.XZQDM'); set b=CONCAT('$.features[',i,'].attributes.XZQMC'); set c=CONCAT('$.features[',i,']'); #打開游標 open cur; #開始循環(huán)游標里的數(shù)據(jù) read_loop:loop #根據(jù)游標當前指向的一條數(shù)據(jù) fetch cur into j; #判斷游標的循環(huán)是否結束 if done then leave read_loop;#跳出游標循環(huán) end if; #這里可以做任意你想做的操作 WHILE i<11 do insert into dt_border(xzq_code,name,border) select json_extract(j,a),json_extract(j,b),json_extract(j,c) from JSON; set i = i + 1; END WHILE; #結束游標循環(huán) end loop; #關閉游標 close cur; #輸出結果 select j,i; END; #調(diào)用存儲過程 call StatisticStore();
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
MySQL執(zhí)行SQL文件報錯:Unknown collation ‘utf8mb4_0900_ai_
這篇文章主要給大家分享了MySQL執(zhí)行SQL文件出現(xiàn)【Unknown collation ‘utf8mb4_0900_ai_ci‘】的解決方案,如果又遇到相同問題的同學,可以參考閱讀本文2023-09-09MySQL數(shù)據(jù)庫中varchar類型的數(shù)字比較大小的方法
varchar類型的數(shù)據(jù)是不能直接比較大小的,那么MySQL數(shù)據(jù)庫中varchar類型如何進行數(shù)字比較大小的,本文就詳細的介紹一下2021-11-11Mysql 切換數(shù)據(jù)存儲目錄的實現(xiàn)方法
這篇文章主要介紹了Mysql 切換數(shù)據(jù)存儲目錄的實現(xiàn)方法的相關資料,需要的朋友可以參考下2017-07-07