JSON类型在日常应用开发中,用得很少,个人通常用于存储常常变化的配置参数。

它适用于什么业务场景,不好说。就好像许多年前读到的一篇文章,说有个国外公司利用ORACLE的CLOB/BLOB管理一些信息,好像还很成功的样子。

所以,客观地说,JSON的价值取决于工程师的能力和业务场景。

MYSQL8.0提供了许多的函数,详细的参阅官网的文档:

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

一、定义JSON字段

MYSQL提供了JSON类型字段,它至少某个程度上和字符类型的表现是一致的。

它和字符类型的主要区别在于:

  1. MYSQL会验证值的合法性。如果定义为varchar,text,那么MYSQL就不会去验证。
  2. 优化存储格式,以二进制的形式存储。读取的时候无需先转为json对象。所以读取更快

总结起来,还是直接定义为JSON类型更好。

至于具体业务场景中,是定义为JSON还是VARCHAR/TEXT之类的,需要看具体需要。

如果我们频繁存取JSON,那么通常还是建议使用JSON类型,而不是字符类型来存储JSON数据。

二、查找/获取值

这是最常用的函数类。

在很多情况下,我们并不使用MYSQL自身提供的JSON函数。

例如我需要把系统配置信息序列化到数据库,那么一般情况下,会直接通过面向对象的序列化功能,把对象序列化为JSON,在直接存入数据库。

但是常常会希望在SQL中获取JSON的某个值,而不希望把数据载入内存,再写代码解析。

MYSQL8关于查询的函数有许多;

JSON_CONTAINS(target, candidate[, path])  -- 类似exists 或者 having

JSON_CONTAINS_PATH(json_doc, one_or_all, path[, path] ...)  --同上

JSON_EXTRACT(json_doc, path[, path] ...)  -- 读取某个键值

JSON_VALUE(json_doc, path)   -- 类似JSON_EXTRACT,但是比后者强,因为JSON_VALUE还可以把结果转为特定类型

JSON_SEARCH(json_doc, one_or_all, search_str[, escape_char[, path] ...])   -- 通过键值获取键路径

... 略

本文只介绍JSON_EXTRACT和JSON_VALUE.

在开始介绍前,先介绍如何访问JSON对象的特定部分的键值,或者说如何书写键路径。

例如有JSON对象文本如下:

{
    "owner": "辛弃疾",
    "book": [
        {
            "name": "武德充沛的必要性",
            "price": 100
        },
        {
            "name": "哲学",
            "price": 90.5
        }
    ],
        "content":{
            "totalPage":456,
            "totalWords":400000
        }
}

这个路径必须以“$.”开头,后面就很好理解--和JAVA包路径一样,不同层级之间通过点号分隔。如果有数组,那么用"[]"表示,下标从0开始。

下面分别写两中路径语法例子:

  • 不带数组-$.k1.k2.k3....kn,其中n>=1
  • 带数组-$.k1.k2[i].k3....kn  ,其中n>=1,i>=0

三、返回结果集

上官方的表达式:

JSON_TABLE(
expr,
path COLUMNS (column_list)
) [AS] alias column_list:
column[, column][, ...] column:
name FOR ORDINALITY
| name type PATH string path [on_empty] [on_error]
| name type EXISTS PATH string path
| NESTED [PATH] path COLUMNS (column_list) on_empty:
{NULL | DEFAULT json_string | ERROR} ON EMPTY on_error:
{NULL | DEFAULT json_string | ERROR} ON ERROR

中括号,逗号以及竖线的含义请参阅mysql官方文档。表达式不难理解,只要看了例子。

但是如果涉及到嵌套等,就会有那么一点复杂了。

on empty,on error字句允许在没有或者发生错误的时候返回替代结果。

当至少在MYSQL8.0.X版本(截至20220623在8.0.29版本)中,这个功能还不是很完美:必须先关联才可以使用。

注:不关联也可以,不过对于我而言意义不大。

在我的一般业务场景中,我希望这样:

SELECT * FROM
json_table(json_extract(t_json.book,'$.book'),
"$[*]" COLUMNS(
NAME VARCHAR(60) path "$.name",
price DECIMAL(10,2) path "$.price"
)
) AS JJ;

但是这个不行的,会提示:

错误代码: 1109
Unknown table 't_json' in a table function argument

四、例子

数据库版本:centos8 mysql8.0.27 企业版(社区版)

建表T_JSON:

CREATE TABLE `t_json` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`book` json DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

插入数据到BOOK字段,内容如下(id略,脚本略):

    {
"book": [
{
"name": "中国的未来",
"price": 100
},
{
"name": "真理-数学",
"price": 100
}
],
"owner": "luzhifei",
"content": {
"totalPage": 945,
"totalWords": 9745556
}
}
------------------------
{
"book": [
{
"name": "武德充沛的必要性",
"price": 100
},
{
"name": "哲学",
"price": 90.5
}
],
"owner": "辛弃疾",
"content": {
"totalPage": 456,
"totalWords": 400000
}
}

1.JSON_VALUE

select JSON_VALUE(book,"$.content.totalPage" RETURNING decimal(10,2)) from t_json;
select JSON_VALUE(book,"$.content.totalPage") from t_json;

注:在8.0.20(windows)下,JSON_VALUE并不存在。

由于JSON_VALUE仅仅等价于(官方):

SELECT CAST(
JSON_UNQUOTE( JSON_EXTRACT(json_doc, path) )
AS type
);

所以,不使用JSON_VALUE,而使用替代脚本也可以。

2.JSON_EXTRACT

SELECT json_extract(book,'$.book') FROM t_json;

查询特定数组中某个key值:SELECT json_extract(book,'$.book[1].name') FROM t_json where id=3;

补充说明,可以使用->或者->>替代JSON_EXTRACT,具体例子见后文JSON_TABLE。

其中:

  1. ->   表示获取可能带有双引号的值
  2. ->> 获取不带双引号的值。通常我们使用这个。

3.JSON_TABLE

SELECT v.id,book->>"$.owner" AS author, book->"$.content.totalPage" AS totalPage,  t.name,t.price FROM t_json v,
json_table(json_extract(v.book,'$.book'),
  "$[*]" COLUMNS(
     NAME VARCHAR(60) path "$.name",
     price DECIMAL(10,2) path "$.price"
  )
) AS t;

SELECT v.id,json_extract(book,"$.owner") AS  author, json_extract(book,"$.content.totalPage") AS totalPage,     t.name,t.price FROM t_json v,
json_table(json_extract(v.book,'$.book'),
  "$[*]" COLUMNS(
     NAME VARCHAR(60) path "$.name",
     price DECIMAL(10,2) path "$.price"
  )
) AS t;

五、小结

JSON字段适用场景比较狭窄,尤其在一般应用开发领域,所以没有怎么关注。

JSON作为MYSQL一种类型补充,有了会方便点,没有也无所谓。

对于大部分程序员而言,JSON类型最大的价值在某些情况下可以于少写了一些代码,前提是你得恰当地适用。

如果业务场景中数据巨量,而且查询更新等都很频繁,不建议你适用这个数据类型,炫技除外!

于我而言,它的主要意义在于黑盒化信息,封装特定的业务,如果使用恰当的话。

例如某个配置又想添加一些属性,那么不需要对表格做任何修改,仅仅只需要修改下后台实现代码(通常情况)。如此,某种程度上有助于实现某种程度的开闭原则。

如果有需要大量使用非结构化数据和JSON的场景,可以考虑使用其它非关系数据库。

MYSQL8.0-JSON函数简单示例-JSON_EXTRACT|JSON_VALUE|JSON_TABLE的更多相关文章

  1. C++ 回调函数简单示例

    回调函数其实就是以函数指针做函数参数传递给另一个函数,在另一个函数执行的时候可以根据函数指针执行回调函数的代码.简单示例,便于理解,防止遗忘. #include <iostream> ty ...

  2. android json 解析 简单示例

    1 下面是一个简单的json 解析的demo,废话不多说,直接上代码 package com.sky.gallery; import java.io.ByteArrayOutputStream; im ...

  3. Python3基础 内嵌函数 简单示例

    镇场诗: 诚听如来语,顿舍世间名与利.愿做地藏徒,广演是经阎浮提. 愿尽吾所学,成就一良心博客.愿诸后来人,重现智慧清净体.-------------------------------------- ...

  4. DB2函数简单示例

    DB2中的函数原理同其他编程语言中的函数,均为输入几个参数,同时返回一个值. 下面的例子演示一个寻找某一次考试中成绩最好的学生的姓名. 首先,我们新建一个表SCORE用于表示考试,并插入几条数据: D ...

  5. angular.fromJson(json)的简单示例

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  6. 【SqlServer】JSON函数

    1   概述 本篇文件将结合MSND简要分析Sqlserver中JSON函数,主要包括ISJSON,JSON_VALUE,JSON_MODIFY,JSON_QUERY. 2   具体内容 2.1  J ...

  7. ABAP分享一 弹出框函数的简单示例

    在开发中经常会使用到弹出框这个功能,在SAP中有很多函数可以实现类似的功能,这里介绍一个比较简单常用的函数  POPUP_TO_CONFIRM 下面是一个实现的简单示例: TABLES sscrfie ...

  8. windows下mysql8.0.x简单安装!

    1.官网下载mysql安装包并解压到自己喜欢的目录 2.在解压的目录下,添加my.ini配置文件,内容如下:[mysqld]# 设置3306端口port=3306# 设置mysql的安装目录 下面是我 ...

  9. MySQL8.0新特性实验1

    Server层,选项持久化 mysql> show variables like '%max_connections%';+------------------------+-------+| ...

  10. Mysql8.0.11简介,新特性

    MySQL 8.0 正式版 8.0.11 已发布,官方表示 MySQL 8 要比 MySQL 5.7 快 2 倍,还带来了大量的改进和更快的性能! 注意:从 MySQL 5.7 升级到 MySQL 8 ...

随机推荐

  1. dotnet 5 的 bin 文件夹下的 ref 文件夹是做什么用的

    本文来和大家聊聊在 dotnet 5 和 dotnet 6 或更高版本的 dotnet 构建完成,在 bin 文件夹下,输出的 ref 文件夹.在此文件夹里面,将会包含项目程序集同名的 dll 文件, ...

  2. Unity3D OpenVR 虚拟现实 保龄球打砖块游戏开发

    据说水哥买了 Valve Index 设备,既然这个设备这么贵,不开发点有(zhi)趣(zhang)游戏就感觉对不起这个设备.本文将来开始着手开发一个可玩性不大,观赏性极强的保龄球打砖块游戏.这仅仅只 ...

  3. ES6中Promise方法详解

    概要 Promise是个保存异步结果的容器(对象). Promise的状态有:pending(进行中),fulfilled(已成功),rejected(已失败),对应其异步操作的状态. 状态转换: p ...

  4. 6.Ingress 七层负载

    官方文档:https://kubernetes.io/zh-cn/docs/concepts/services-networking/ingress/题目: 设置配置环境: [candidate@no ...

  5. kubernetes-1.26安装

    一.环境准备 k8s集群角色 IP 主机名 安装组件 配置 控制节点 192.168.10.10 master apiserver.controller-manager.scheduler.etcd. ...

  6. PostMan接口测试实用小点

    PostMan接口测试实用小点 1. 接口测试变量存取操作 在Postman中有很多地方可以存储一些变量,这里只介绍经常使用的环境变量.变量设置后,在UI界面可以通过{{变量名}}获取到对应值. 在环 ...

  7. js的几个截取

    jsfun(){         let str = '01234567'         let str1         str1 = str.slice(2,5)                 ...

  8. 【简说Python WEB】Jinja2模板

    目录 [简说Python WEB]Jinja2模板 目前环境的代码树 抽离出来的Html模板 渲染模板 条件语句 循环语句 系统环境:Ubuntu 18.04.1 LTS Python使用的是虚拟环境 ...

  9. LLaMA 3 源码解读-大语言模型5

    本来不是很想写这一篇,因为网上的文章真的烂大街了,我写的真的很有可能没别人写得好.但是想了想,创建这个博客就是想通过对外输出知识的方式来提高自身水平,而不是说我每篇都能写得有多好多好然后吸引别人来看. ...

  10. 用pageOffice控件实现 office word文档 强制留痕编辑Word

    OA办公中,业务需要多人编辑word文档,需要强制留痕功能,用来查看文档编辑过程中的具体修改痕迹. 怎么实现word文档的强制留痕呢? 1 实现方法 通过pageOffice实现简单的在线打开编辑wo ...