当前位置: 首页 > article >正文

MySQL更新JSON字段key:value形式

MySQL更新JSON字段key:value形式

1. 介绍

‌MySQL的JSON数据类型‌是MySQL 5.7及以上版本中引入的一种数据类型,用于存储JSON格式的数据。使用JSON数据类型可以自动校验文档是否满足JSON格式的要求,优化存储格式,并允许快速访问文档中的特定元素,而无需读取整个文档

2. 针对key:value形式

初始场景:MySQL的JSON字段存储的数据形式

[
  {
    "code": "test",
    "value": "暂无"
  }
  

调用方法会获取到执行的value的值,依据code,如果存在进行更新,不存在进行添加。

update_sql = f"""
                        UPDATE {table_name}
                        SET props = CASE
                                      WHEN JSON_SEARCH(props, 'one', :code, NULL, '$[*].code') IS NOT NULL THEN
                                        JSON_SET(
                                            props,
                                            REPLACE(JSON_UNQUOTE(JSON_SEARCH(props, 'one', :code, NULL, '$[*].code')), '.code', '.value'),
                                            :result
                                        )
                                      ELSE
                                        JSON_ARRAY_APPEND(
                                            IFNULL(props, JSON_ARRAY()), 
                                            '$', 
                                            JSON_OBJECT('code', :code, 'value', :result)
                                        )
                                    END,
                            updated_at = NOW()
                        WHERE id = :id
                    """

                    # 执行 SQL 更新
                    session_new.execute(text(update_sql), {
                        'code': code,
                        'result': result,
                        'id': id
                    })

进阶场景:MySQL的JSON字段存储的数据形式

[
  {
    "code": "test2",
    "value": "暂无",
    "update_time": "2024-11-28 19:13:12"
  }
]

获取的不再是单个value的值,而是一个dict,示例:

{
  "code": "test2",
  "value": "暂无数据",
  "test_id": 2,
  "all_test_id": 2,
  "aaaa": "12",
  "update_time": "2023-12-23 00:00:00"
}

依据code,如果存在进行更新,不存在进行添加,只是这次执行需要更新多个key:value形式数据。
示例,可执行sql:

UPDATE intention_extended_datas
SET 
    props = CASE
        WHEN JSON_SEARCH(props, 'one', 'test2', NULL, '$[*].code') IS NOT NULL THEN
            JSON_SET(
                JSON_SET(
                    JSON_SET(
                        JSON_SET(
                            JSON_SET(
                                props,
                                REPLACE(JSON_UNQUOTE(JSON_SEARCH(props, 'one', 'test2', NULL, '$[*].code')), '.code', '.value'),
                                '暂无'
                            ),
                            REPLACE(JSON_UNQUOTE(JSON_SEARCH(props, 'one', 'test2', NULL, '$[*].code')), '.code', '.test_id'),
                            2
                        ),
                        REPLACE(JSON_UNQUOTE(JSON_SEARCH(props, 'one', 'test2', NULL, '$[*].code')), '.code', '.all_test_id'),
                        3
                    ),
                    REPLACE(JSON_UNQUOTE(JSON_SEARCH(props, 'one', 'test2', NULL, '$[*].code')), '.code', '.aaa'),
                    '226'
                ),
                REPLACE(JSON_UNQUOTE(JSON_SEARCH(props, 'one', 'test2', NULL, '$[*].code')), '.code', '.update_time'),
                '2023-12-26 00:00:00'
            )
        ELSE
            JSON_ARRAY_APPEND(
                IFNULL(props, JSON_ARRAY()), 
                '$', 
                JSON_OBJECT(
                    'code', 'test2', 
                    'value', '暂无数据', 
                    'test_id', 1,
                    'all_test_id', 2, 
                    'aaa', '223',
                    'update_time', '2023-12-23 00:00:00'
                )
            )
    END,
    updated_at = NOW()
WHERE id = 1;

python代码如何实现这样的可执行sql,ressult是dict格式:

    def generate_update_sql(self, table_name, result) -> str:
        # 构建 SET 部分的 SQL
        set_sql_parts = []

        # 构建 WHEN 子句
        when_clause = f"""
            WHEN JSON_SEARCH(props, 'one', :code, NULL, '$[*].code') IS NOT NULL THEN
                {self.construct_json_set_query(result)}
        """
        set_sql_parts.append(when_clause)

        # 构建 ELSE 子句,添加新的元素到 JSON 数组
        else_clause = f"""
            ELSE
                JSON_ARRAY_APPEND(
                    IFNULL(props, JSON_ARRAY()),
                    '$',
                    JSON_OBJECT(
                        'code', :code,
                        {', '.join([f"'{key}', :{key}" for key in result.keys()])}
                    )
                )
        """
        set_sql_parts.append(else_clause)

        # 构建更新语句
        set_sql = f"""
            UPDATE {table_name}
            SET props = CASE
                {" ".join(set_sql_parts)}
            END,
            updated_at = NOW()
            WHERE id = :id;
        """

        return set_sql

    @staticmethod
    def construct_json_set_query(dynamic_data: dict) -> str:
        """
        根据传入的动态字典,构造 JSON_SET 的嵌套语句。

        :param dynamic_data: 动态字典,键为路径后缀,值为占位符。
                             示例:{"value": ":value", "test_id": ":test_id"}
        :return: 返回生成的 SQL JSON_SET 嵌套语句。
        """
        if not dynamic_data:
            return "props"  # 如果没有键值对,直接返回基础结构

        base_path = "REPLACE(JSON_UNQUOTE(JSON_SEARCH(props, 'one', :code, NULL, '$[*].code')), '.code', '{}')"
        json_set_template = "JSON_SET({}, {}, {})"

        # 构造嵌套 JSON_SET 语句
        nested_set = "props"
        for key, placeholder in dynamic_data.items():
            replace_path = base_path.format(f".{key}")  # 替换路径
            nested_set = json_set_template.format(nested_set, replace_path, f':{key}')

        return nested_set

外部调用

# 如果是 JSON 字段,需要检查是否存在,并进行更新或追加
                    update_sql = self.generate_update_sql(table_name, result)
                    # 格式化 SQL
                    formatted_sql = sqlparse.format(update_sql, reindent=True, keyword_case='upper')
                    # 执行 SQL 更新,将 result 中的所有键值对与 code 和 id 一起传递
                    session_new.execute(text(formatted_sql), {
                        'code': code,
                        'id': id,
                        **result
                    })

http://www.kler.cn/a/416577.html

相关文章:

  • FreeSWITCH 简单图形化界面36 -使用mod_sms发送短消息
  • Z2400039基于Java+MySQL+SpringBoot + vue 企业信息管理系统的设计与实现 代码 文档
  • 求100之内的素数-多语言
  • 在鸿蒙应用中 Debug 对开发者的帮助
  • 单细胞细胞通讯全流程分析教程,代做分析和辅导
  • HCIA笔记6--路由基础
  • Flink解决延迟数据问题
  • PostgreSQL 中Identity Columns生成一个唯一的标识符
  • Grafana插件安装并接入zabbix数据源
  • 速盾高防cdn支持移动端独立缓存
  • 基于 LlamaFactory 的 LoRA 微调模型支持 vllm 批量推理的实现
  • Go语言技巧:快速统一字符串中的换行符,解决跨平台问题
  • T507 buildroot linux4.9之RTC8563开发调试
  • SQLModel与FastAPI结合:构建用户增删改查接口
  • 海盗王用golang重写的AccountServer功能
  • Facebook Audience Network优化指南
  • 学习笔记042——如何通过IDEA中自带的数据库组件导出MySQL数据
  • Jmeter测试工具的安装和使用,mac版本,jmeter版本5.2.1
  • 《向量数据库指南》——稀疏激活:解锁大数据处理新纪元
  • 【游戏引擎之路】登神长阶(十五)——DirectX12龙书:行百里者半九十(学习阶段完结)
  • 介绍一下atoi(arr);(c基础)
  • 汽车驾校寒冬,新增无人机飞手培训技术详解
  • GPT打字机效果—— fetchEventSouce进行sse流式请求
  • Oracle LinuxR7安装Oracle 12.2 RAC集群实施(DNS解析)
  • 【大数据学习 | Spark-SQL】定义UDF和DUAF,UDTF函数
  • 使用Java来构筑一个基础的项目完全梳理(二):前端vue搭建