详解Mysql中的JSON系列操作函数

一、方法罗列:

分类 函数 描述
创建json
json_array 创建json数组
json_object 创建json对象
json_quote 将json转成json字符串类型
查询json
json_contains 判断是否包含某个json值
json_contains_path 判断某个路径下是否包json值
json_extract 提取json值
column->path json_extract的简洁写法,MySQL 5.7.9开始支持
column->>path json_unquote(column -> path)的简洁写法
json_keys 提取json中的键值为json数组
json_search 按给定字符串关键字搜索json,返回匹配的路径
修改json
json_append 废弃,MySQL 5.7.9开始改名为json_array_append
json_array_append 末尾添加数组元素,如果原有值是数值或json对 象,则转成数组后,再添加元素
json_array_insert 插入数组元素
json_insert 插入值(插入新值,但不替换已经存在的旧值)
json_merge 合并json数组或对象
json_remove 删除json数据
json_replace 替换值(只替换已经存在的旧值)
json_set 设置值(替换旧值,并插入不存在的新值)
json_unquote 去除json字符串的引号,将值转成string类型
返回json属性
json_depth 返回json文档的最大深度
json_length 返回json文档的长度
json_type 返回json值得类型
json_valid 判断是否为合法json文档

二、使用例子:

MySQL 5.7.8开始支持 json类型.

create table t(id int,js json,PRIMARY KEY (id))

插入数据
insert into t values(1,'{"a":1,"s":"abc"}')
insert into t values(2,'[1,2,{"a":123}]')
insert into t values(3,'"str"')
insert into t values(4,'123')

直接提供字符串即可。还可以用JSON_Array和JSON_Object函数来构造
insert into t values(5,JSON_Object('key1',v1,'key2',v2))
insert into t values(4,JSON_Array(v1,v2,v3))

JSON_OBJECT([key, val[, key, val] ...])
JSON_ARRAY([val[, val] ...])

JSON_SET(json_doc, path, val[, path, val] ...)
修改数据

update t set js=json_set('{"a":1,"s":"abc"}','$.a',456,'$.b','bbb') where id=1

结果js={"a":456,"s":"abc","b":"bbb"}

path中就代表整个doc,然后可以用[JavaScript](http://lib.csdn.net/base/javascript "JavaScript知识库")的方式指定对象属性或者数组下标等. 执行效果,类似json的语法.a=456
$.b="bbb"
存在就修改,不存在就设置.

$.c.c=123

这个在javascript中会出错,因为.c为null。
但是在json_set('{}','$.c.c',123)中,不存在的路径将直接被忽略。

特殊的对于数组,如果目标doc不是数组则会被转换成[doc],然后再执行set,
如果set的下标超过数组长度,只会添加到数组结尾。

select json_set('{"a":456}','$[1]',123)

结果[{"a":456},123]。目标现被转换成[{"a":456}],然后应用$[1]=123。

select json_set('"abc"','$[999]',123)
结果["abc",123]。

再举几个例子

select json_set('[1,2,3]','$[0]',456,'$[3]','bbb')

结果[456,2,3,'bbb']

注意:
对于javascript中
var a=[1,2,3]
a.a='abc'
是合法的,但是一旦a转成json字符串,a.a就丢失了。

而在mysql中,这种算作路径不存在,因此
select json_set('[1,2,3]','$.a',456)
结果还是[1,2,3]

然后还有另外两个版本
JSON_INSERT(json_doc, path, val[, path, val] ...)
如果不存在对应属性则插入,否则不做任何变动

JSON_REPLACE(json_doc, path, val[, path, val] ...)
如果存在则替换,否则不做任何变动

这两个操作倒是没有javascript直接对应的操作

select json_insert('{"a":1,"s":"abc"}','$.a',456,'$.b','bbb')
结果{"a":1,"s":"abc","b":"bbb"}

select json_replace('{"a":1,"s":"abc"}','$.a',456,'$.b','bbb')
结果{"a":456,"s":"abc"}

加上删除节点
JSON_REMOVE(json_doc, path[, path] ...)
如果存在则删除对应属性,否则不做任何变动
select json_replace('{"a":1,"s":"abc"}','.a','.b')
结果{"s":"abc"}

涉及数组时,三个函数与json_set基本一样
select json_insert('{"a":1}','$[0]',456)
结果不变,认为0元素已经存在了,注意这里结果不是[{"a":1}]

select json_insert('{"a":1}','$[999]',456)
结果追加到数组结尾[{"a":1},456]

select json_replace('{"a":1}','$[0]',456)
结果456!而非[456]

select json_replace('{"a":1}','$[1]',456)
结果不变。

其实对于json_insert和json_replace来说一般情况没必要针对数组使用。

select json_remove('{"a":1}','$[0]')
结果不变!

select json_remove('[{"a":1}]','$[0]')
结果[]

总之涉及数组的时候要小心。

JSON_MERGE(json_doc, json_doc[, json_doc] ...)
将多个doc合并

select json_merge('[1,2,3]','[4,5]')
结果[1,2,3,4,5]。数组简单扩展

select json_merge('{"a":1}','{"b":2}')
结果{"a":1,"b":2}。两个对象直接融合。

特殊的还是在数组
select json_merge('123','45')
结果[123,45]。两个常量变成数组

select json_merge('{"a":1}','[1,2]')
结果[{"a":1},1,2]。目标碰到数组,先转换成[doc]

select json_merge('[1,2]','{"a":1}')
结果[1,2,{"a":1}]。非数组都追加到数组后面。

JSON_ARRAY_APPEND(json_doc, path, val[, path, val] ...)
给指定的节点,添加元素,如果节点不是数组,则先转换成[doc]

select json_Array_append('[1,2]','/article>,'456')
结果[1,2,456]

select json_Array_append('[1,2]','$[0]','456')

结果[[1,456],2]。指定插在[0]这个节点,这个节点非数组,所以等效为 select json_Array_append('[[1],2]','[0]','456')

JSON_ARRAY_INSERT(json_doc, path, val[, path, val] ...)
在数组的指定下标处插入元素

SELECT JSON_ARRAY_INSERT('[1,2,3]','$[1]',4)
结果[1,4,2,3]。在$数组的下标1处插入

SELECT JSON_ARRAY_INSERT('[1,[1,2,3],3]','$[1][1]',4)
结果[1,[1,4,2,3],3]。在$[1]数组的下标1处插入

SELECT JSON_ARRAY_INSERT('[1,2,3]','$[0]',4,'$[1]',5)
结果[4,5,1,2,3]。注意后续插入是在前面插入基础上的,而非[4,1,5,2,3]

提取json信息的函数
JSON_KEYS(json_doc[, path])
返回指定path的key

select json_keys('{"a":1,"b":2}')
结果["a","b"]

select json_keys('{"a":1,"b":[1,2,3]}','$.b')
结果null。数组没有key

JSON_CONTAINS(json_doc, val[, path])
是否包含子文档

select json_contains('{"a":1,"b":4}','{"a":1}')
结果1

select json_contains('{"a":2,"b":1}','{"a":1}')
结果0

select json_contains('{"a":[1,2,3],"b":1}','[1,2]','$.a')
结果1。数组包含则需要所有元素都存在。

select json_contains('{"a":[1,2,3],"b":1}','1','$.a')
结果1。元素存在数组元素中。

JSON_CONTAINS_PATH(json_doc, one_or_all, path[, path] ...)
检查路径是否存在

select JSON_CONTAINS_PATH('{"a":1,"b":1}', 'one','$.a','$.c')
结果1。只要存在一个

select JSON_CONTAINS_PATH('{"a":1,"b":1}', 'all','$.a','$.c')
结果0。必须全部存在。

select JSON_CONTAINS_PATH('{"a":1,"b":{"c":{"d":1}}}', 'one','$.b.c.d')
结果1。

select JSON_CONTAINS_PATH('{"a":1,"b":{"c":{"d":1}}}', 'one','$.a.c.d')
结果0。

JSON_EXTRACT(json_doc, path[, path] ...)
获得doc中某个或多个节点的值。

select json_extract('{"a":1,"b":2}','$.a')
结果1

select json_extract('{"a":[1,2,3],"b":2}','$.a[1]')
结果2

select json_extract('{"a":{"a":1,"b":2,"c":3},"b":2}','$.a.')
结果[1,2,3]。a.
通配a所有属性的值返回成数组。

select json_extract('{"a":{"a":1,"b":2,"c":3},"b":4}','$**.b')
结果[2,4]。通配$中所有层次下的属性b的值返回成数组。

mysql5.7.9开始增加了一种简写方式:column->path

select id,js->'$.id' from t where js->'$.a'=1 order by js->'$.b'
等价于
select id,json_extract(js,'$.id') 
from t where json_extract(js,'$.a')=1
order by json_extract(js,'$.b')

JSON_SEARCH(json_doc, one_or_all, search_str[, escape_char[, path] ...])
强大的查询函数,用于在doc中返回符合条件的节点,select则是在表中返回符合要求的纪录。

select json_search('{"a":"abc","b":{"c":"dad"}}','one','%a%')

结果$.a。和like一样可以用%和_匹配,在所有节点的值中匹配,one只返回一个。

select json_search('{"a":"abc","b":{"c":"dad"}}','all','%a%')
结果["$.a","$.b.c"]

select json_search('{"a":"abc","b":{"c":"dad"}}','all','%a%',null,'$.b')
结果["$.b.c"]。限制查找范围。

select json_search('{"a":"abc","b":{"c":"dad"},"c":{"b":"aaa"}}','all','%a%',null,'$**.b')
结果["$.b.c","$.c.b"]。查找范围还可使用通配符!在每个匹配节点和其下查找。

注意,只有json_extract和json_search中的path才支持通配,其他json_set,json_insert等都不支持。

JSON_LENGTH(json_doc[, path])
返回数组的长度,如果是object则是属性个数,常量则为1

select json_length('[1,2,3]')
结果3

select json_length('123')
结果1

select json_length('{"a":1,"b":2}')
结果2

可再跟path参数
select json_length('{"a":1,"b":[1,2,3]}','$.b')
结果3

JSON_DEPTH(json_doc)
返回doc深度

select json_depth('{}'),json_depth('[]'),json_depth('123')
结果1,1,1

select json_depth('[1,2,3,4,5,6]')
结果2

select json_depth('{"a":{"b":{"c":1}}}')
结果4

参考:
http://www.jb51.net/article/89219.htm
http://blog.csdn.net/joker_honey/article/details/53081716

原文:
https://blog.csdn.net/jiangyu1013/article/details/78917425

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,653评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,321评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,833评论 0 324
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,472评论 1 266
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,306评论 4 357
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,274评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,658评论 3 385
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,335评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,638评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,697评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,454评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,311评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,699评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,986评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,254评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,647评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,847评论 2 335

推荐阅读更多精彩内容