当前位置:首页 > 文章列表 > 数据库 > MySQL > MySQL JSON_TABLE怎样把缺失字段和 JSON null 区分开

MySQL JSON_TABLE怎样把缺失字段和 JSON null 区分开

来源:17golang原创 2026-11-04 08:41:28 0浏览 收藏

用 MySQL JSON_TABLE() 把半结构化数据转成列时,我最容易踩到的坑不是路径写错,而是把“字段不存在”和“字段明确写成 JSON null”看成同一件事。普通的 PATH 列在这两种情况下都可能得到 SQL NULL,后续清洗、补默认值或统计时就会失去原始语义。

更稳妥的做法是把“字段是否出现”和“字段取出的值”拆成两列:用 EXISTS PATH 保存存在性,用普通 PATH 列保存值,再根据 ON EMPTY 和 ON ERROR 处理缺失与类型错误。

官方地址:https://dev.mysql.com/doc/refman/8.4/en/json-table-functions.html

先把三种状态分开

假设输入文档中有三种记录:

  • {"name":"Ada"}:字段存在,值是字符串。
  • {}:字段缺失,路径找不到值。
  • {"name":null}:字段存在,但值明确是 JSON null。

如果只写一个 name VARCHAR(64) PATH '$.name',后两种情况都可能表现为 SQL NULL。这时查询结果无法回答“用户没有传这个字段”还是“用户传了 null”。因此要把存在性变成显式标记。

JSON_TABLE 通过 EXISTS PATH 和 PATH 列区分字段存在、字段缺失与 JSON null 的结构说明图
图1:JSON_TABLE 区分字段是否出现与字段值的静态说明图,不是截图或运行证据。

用 EXISTS PATH 记录字段是否出现

EXISTS PATH 列只回答一个问题:指定路径上是否有数据。它通常使用整数类型,返回 1 或 0。把它和普通值列放在同一个 COLUMNS 中,就能保留两个维度。

SELECT jt.name_present, jt.name_value
FROM JSON_TABLE(
  '[{"name":"Ada"},{},{"name":null}]',
  '$[*]' COLUMNS(
    -- 只记录 $.name 是否出现,不负责返回姓名
    name_present INT EXISTS PATH '$.name',
    -- 读取姓名;缺失值默认按 NULL 处理
    name_value VARCHAR(64) PATH '$.name' NULL ON EMPTY NULL ON ERROR
  )
) AS jt;

这组列的解释是:

输入状态name_presentname_value业务含义
字段有字符串1Ada有值
字段缺失0NULL未提供
显式 JSON null1NULL主动置空

关键点是第三行:值列仍然是 NULL,但存在性列为 1,所以它和第二行可以区分。这个标记也适合写入中间表,之后再决定是否覆盖旧值。

ON EMPTY 和 ON ERROR 怎么配

这两个子句处理的是不同问题。ON EMPTY 针对路径没有匹配值的情况;ON ERROR 针对取到的 JSON 值无法按目标列类型保存的情况,例如把对象或数组写进标量列。它们不是用来替代 EXISTS PATH 的,因为默认值只能改变输出值,不能告诉你字段是否出现。

SELECT jt.name_present, jt.name_value
FROM JSON_TABLE(
  '[{"name":"Ada"},{},{"name":{"raw":true}}]',
  '$[*]' COLUMNS(
    -- 存在性独立于值处理,便于区分缺失和显式 null
    name_present INT EXISTS PATH '$.name',
    -- 缺失时保留占位文本;类型无法转换时返回 NULL
    name_value VARCHAR(64) PATH '$.name'
      DEFAULT '未提供' ON EMPTY
      NULL ON ERROR
  )
) AS jt;

若业务要求输入严格,建议把 ERROR ON EMPTY 或 ERROR ON ERROR 用在导入边界,让脏数据尽早失败;若业务允许渐进清洗,可以用 DEFAULT 记录占位值,同时保留 EXISTS PATH 供后续判断。

MySQL JSON_TABLE 的 ON EMPTY 与 ON ERROR 处理分支静态对比图
图2:ON EMPTY 与 ON ERROR 分支的静态处理示意图,不是截图或运行证据。

把判断放进实际查询

在真实表中,JSON 文档通常来自一列。JSON_TABLE() 可以引用前面表的列,适合在查询阶段先展开状态,再决定更新策略。

SELECT
  e.id,
  jt.nickname_present,
  jt.nickname_value,
  CASE
    -- 未出现和显式 null 走不同业务分支
    WHEN jt.nickname_present = 0 THEN '保持原值'
    WHEN jt.nickname_value IS NULL THEN '清空昵称'
    ELSE '更新昵称'
  END AS action_name
FROM event_payload AS e
JOIN JSON_TABLE(
  e.payload,
  '$' COLUMNS(
    -- 先保留键是否出现的事实
    nickname_present INT EXISTS PATH '$.nickname',
    -- 再读取可写入的字符串值
    nickname_value VARCHAR(64) PATH '$.nickname' NULL ON EMPTY NULL ON ERROR
  )
) AS jt;

这里的 CASE 顺序很重要:先判断存在性为 0,再判断值是否为 SQL NULL。如果先只写 nickname_value IS NULL,缺失字段和显式 JSON null 就会重新合并。

常见误区和选择建议

  • 误区一:用 COALESCE 判断是否缺失。 COALESCE 只能处理结果值,无法恢复字段是否出现;应保留 EXISTS PATH。
  • 误区二:把 DEFAULT 当成存在性标记。 缺失字段被填成默认文本后,原始状态已经被覆盖;需要同时保留标记列。
  • 误区三:把 ON ERROR 当成缺失处理。 路径不匹配属于 ON EMPTY,对象、数组或类型转换失败属于 ON ERROR。
  • 误区四:用字符串比较 JSON null。 JSON null 不是字符串 "null";若业务必须区分它与缺失,使用存在性列加值列,不要靠文本替换。

一张表记住组合方式

目标推荐写法理由
判断键是否出现INT EXISTS PATH保留存在性事实
读取字符串或数字type PATH把 JSON 值转成目标 SQL 类型
路径无值时给占位值DEFAULT ... ON EMPTY为后续流程提供可识别默认值
类型错误必须暴露ERROR ON ERROR阻止脏数据静默进入结果
允许错误但保留 NULLNULL ON ERROR适合宽松清洗流程,但要配合日志或状态列

结语

要区分 MySQL JSON_TABLE() 中的字段缺失和显式 JSON null,不要试图从一个普通值列里猜答案。用 EXISTS PATH 记录“有没有这个键”,用 PATH 读取“键对应的值”,再按数据质量要求配置 ON EMPTY 与 ON ERROR,这套组合既清晰又容易扩展到导入、更新和审计流程。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
MySQL recursive CTE怎样限制递归查询深度MySQL recursive CTE怎样限制递归查询深度
上一篇
MySQL recursive CTE怎样限制递归查询深度
MySQL GIS ST_Distance_Sphere怎样计算经纬度近似距离
下一篇
MySQL GIS ST_Distance_Sphere怎样计算经纬度近似距离
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    879次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    875次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    957次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    939次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    766次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码