令人惊讶的是,我找不到很多关于在MySQL中比较两个JSON数据类型字段的信息.人们似乎总是将JSON字段与转换为JSON对象的字符串进行比较. 无论如何,我希望这不是一个错误,有人能告诉我如何处理:

我有两张桌子.

CREATE TABLE 
    test 
    ( 
        p_id VARCHAR(40), 
        p_json json 
    ) ;

CREATE TABLE 
    test2 
    ( 
        p_id VARCHAR(40), 
        p_json json 
    ) ;

我在每一张桌子上都放了一条记录.这条记录looks不同,但它确实是相同的JSON对象,因为ordering of keys and values should not matter…即使在嵌套数组的对象中..

 insert into test values ('1',cast('{"recs": [{"priority": 2, "code": "204666"}, {"priority": 1, "code": "204624"}]}' as json));
 insert into test2 values ('1',cast('{"recs": [{"priority": 1, "code": "204624"}, {"priority": 2, "code": "204666"}]}' as json));

现在,当我try 比较这两个json记录时,它们被视为不同的对象.

select t.*
from test t
join test2 t2 on t.p_json = t2.p_json
 ;

但没有记录返回.我希望记录被返回,因为对象实际上是相同的,只要json对象go .对吧?

我的json对象要复杂得多,有许多嵌套的数组,等等.所以我真的希望没有人建议我需要分解对象并分别比较子对象/数组和值.

推荐答案

它们不是同一个JSON文档.

JSON对象键是无序的,MySQL会将其规范化.

mysql> select cast('{"priority": 2, "code": "204666"}' as json)
            = cast('{"code": "204666", "priority": 2}' as json) 
            as json_objects_are_equal;
+------------------------+
| json_objects_are_equal |
+------------------------+
|                      1 |
+------------------------+

但是JSON数组是有序的.也就是说,[0]表示数组中的第一个元素,[1]表示数组中的第二个元素,依此类推.

mysql> select cast('[1, 2]' as json) 
            = cast('[2, 1]' as json)
            as json_arrays_are_equal;
+-----------------------+
| json_arrays_are_equal |
+-----------------------+
|                     0 |
+-----------------------+

我不能建议您分解数组,因为我不知道您想要做什么.但是您应该了解JSON的行为,并相应地编写您的查询.

https://dev.mysql.com/doc/refman/8.2/en/json.html#json-comparison表示:

如果两个JSON数组具有相同的长度并且值in corresponding positions in the arrays相等,则它们相等.

(重点是我的)

Mysql相关问答推荐

为什么IN子句中有GROUP BY会导致查询变得不可执行?

配置MySQL服务器以管理数千个表

如果WHERE语句包含所有列,唯一键顺序是否重要?

SQL:CAST与窗口函数组合导致语法错误

MySQL有没有办法直接从CSV文件中读取而不是导入它?

计算男生的人数和女生的人数.学生是有入学记录的人

MySQL 8.0 可以在 Select 语句中返回 JSON 对象数组吗?

任何值的 SQL WHERE 子句?

如何根据 R 中的价格范围将数据从一列复制到新列?

为什么没有创建此触发器?

当用它的别名替换 (MAX(s.salary) - MIN(s.salary) 它将不起作用.. 为什么?

如何在任何连续范围内获得最大值

如何按给定开始日期和结束日期的月份汇总?

SQL UPDATE中的str_replace?

没有 JDBC 类型的方言映射:1111

为什么数据库行元组中的整数具有L后缀?

在 MySQL 中重命名外键列

如何改进 INSERT INTO ... SELECT 锁定行为

获得上个月的第一天和最后一天的最佳方式?

带有 WHERE 子句的 MySql 内连接