【问题标题】:How to perform add, update and delete on this complex json data type field in MySQL?如何在 MySQL 中对这个复杂的 json 数据类型字段进行添加、更新和删除?
【发布时间】:2021-09-17 07:43:18
【问题描述】:

我对 MySQL 中的 JSON 数据类型完全陌生。几天前我安装了 MySQL 5.7.34,现在我正在使用它。

所以,我在MySQL 5.7.34 中有下表:

CREATE TABLE tb_products (
    product_id int(11) NOT NULL AUTO_INCREMENT, 
    product_name varchar(255) NOT NULL, 
    product_attributes json NOT NULL,
    PRIMARY KEY (product_id)
);

此表中的一行如下所示:

product_attributes 字段:

[
    {
        "site": "site1",
        "categories": [
            "site1 cat1",
            "site1 cat2",
            "site1 cat3"
        ]
    },
    {
        "site": "site2",
        "categories": [
            "site2 cat1",
            "site2 cat2"
        ]
    }
]

我的第一个问题是,我是否以适当的格式放置了 JSON 数据以进行各种进一步的操作?

或者是否应该有一个密钥attributes以便于访问数据:

{
    "attributes": [
        {
            "site": "site1",
            "categories": [
                "site1 cat1",
                "site1 cat2",
                "site1 cat3"
            ]
        },
        {
            "site": "site2",
            "categories": [
                "site2 cat1",
                "site2 cat2"
            ]
        }
    ]
}

现在,我需要执行以下操作,但我不知道该怎么做:

  1. 如何选择site = site1所在的行?
  2. 如何选择site = site1和categories = site1 cat1所在的行?
  3. 如何将另一个对象{"site": "site3", "categories": [...] 添加到product_attributes 列?
  4. 如何添加另一个数组元素site1 cat4 where site = site1?
  5. 如何删除属性site = site1?
  6. 如何从site1 cat1 where site = site1 的类别中删除数组值?

【问题讨论】:

标签: mysql mysql-5.7 mysql-json


【解决方案1】:
  1. 鉴于您所展示的内容,无需将此 JSON 转换为具有 attributes 键的对象。我没有看到任何其他密钥在使用中,您也没有提到添加第二个密钥的任何期望。

  2. 如何选择site = site1所在的行?

    select product_id from tb_products 
    where json_contains(product_attributes, '{"site":"site1"}');
    
  3. 如何选择site = site1和categories = site1 cat1所在的行?

    select product_id from tb_products
    where json_contains(product_attributes, '{"site":"site1"}')
     and json_search(product_attributes, 'one', 'site1 cat2') LIKE '%.categories[%';
    
  4. 如何将另一个对象{"site": "site3", "categories": [...] 添加到product_attributes 列?

    update tb_products 
    set product_attributes = json_array_append(product_attributes, '$', 
      cast('{"site": "site3", "categories":["..."]}' as json));
    
  5. 如何添加另一个数组元素"site1 cat4" where site = site1?

    这是通过键和值查找元素。在 JSON 中执行此操作的更好解决方案是 MySQL 8.0 中的 JSON_TABLE() 函数。在 MySQL 5.7 中没有很好的方法。

    你最终会做JSON_SEARCH(),它只按值搜索,然后你必须在它返回的路径上进行子字符串匹配。这对你来说很难开发,很难维护代码,也无法优化。

  6. 如何删除属性site = site1?

    同上。

  7. 如何从site1 cat1 where site = site1@ 的类别中删除数组值?

    同上。

最终,如果您尝试在普通 SQL 表中使用类似 JSON 的行,将会很尴尬且效率低下。逐渐地,MySQL 正在添加更多 JSON 函数来执行必要的操作,但它并不像在 SQL 中做同样的事情那样优雅。

另一个问题:在 WHERE 子句中搜索 JSON 数据时不能使用索引。你最终会做很多昂贵的表扫描。

还有一个问题:在 JSON 中存储数据所占用的空间是在普通行和列中存储相同数据的 2 到 3 倍。随着您的数据库变得越来越大,您将很快耗尽空间。

【讨论】:

  • 谢谢比尔。很高兴看到您有兴趣回答我的问题。
  • 你可能会喜欢我的演讲How to Use JSON in MySQL Wrong。
  • 查询 2: SELECT * FROM tb_products WHERE JSON_CONTAINS( product_attributes, '{"site":"site1"}' ) AND JSON_CONTAINS( JSON_EXTRACT( JSON_EXTRACT( product_attributes, '$[*] .categories' ), '$[0]' ), '"site1 cat1"' )
  • @IndraKumarS 谢谢,您可能想自己发布答案。但它支持我试图说明的观点,即使用 JSON 比使用普通行和列更难。
  • @BillKarwin 所以我在 MySQL 5.7.34 中的最后 3 个问题没有直接的解决方案吗?顺便说一句,我浏览了你的演示文稿。信息量很大。
猜你喜欢
  • 2022-01-17
  • 2018-11-14
  • 1970-01-01
  • 2017-07-16
  • 2016-04-22
  • 2021-06-03
  • 2021-08-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多