MySQL 5 从 json 数组中的整数连接

MySQL 5 join from integers in json array

有什么方法可以用 MySQL 5 完成这个吗?

我有两个 tables usersroles

用户

 desc users;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | YES  |     | NULL    |       |
| data  | json    | YES  |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
2 rows in set (0.00 sec)


 select * from users;
 +------+------------------------------------+
 | id   | data                               |
 +------+------------------------------------+
 |    1 | {"name": "cat", "roleIds": [2, 3]} |
 |    2 | {"name": "dog", "roleIds": [1, 4]} |
 |    3 | {"name": "mouse", "roleIds": [5]}  |
 +------+------------------------------------+
 3 rows in set (0.00 sec)

角色

desc roles;
+---------+-------------+------+-----+---------+-------+
| Field   | Type        | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| role_id | int(11)     | NO   |     | 0       |       |
| name    | varchar(64) | NO   |     | NULL    |       |
+---------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

select * from roles;
+---------+-------------+
| role_id | name        |
+---------+-------------+
|       1 | Admin       |
|       2 | Supervisor  |
|       3 | Provisioner |
|       4 | Operator    |
|       5 | Relief      |
+---------+-------------+
5 rows in set (0.01 sec)

我想用角色名称修改用户 table 中的 json 数据 结果看起来像这样

+------+------------------------------------------------------------------------------+
| id   | data                                                                         |
+------+------------------------------------------------------------------------------+
|    1 | {"name": "cat", "roleIds": [2, 3], "roleNames": "[Supervisor, Provisioner]"} |
|    2 | {"name": "dog", "roleIds": [1, 4], "roleNames": "[Admin, Operator]"}         |
|    3 | {"name": "mouse", "roleIds": [5], "roleNames": "[Relief]"}                   |
+------+------------------------------------------------------------------------------+

这是使用 json_set()json_contains()json_arrayagg() 的一种方法,它们都在 MySQL 5.7 中可用(后者在版本 5.7.22 中引入) :

select u.id,
    json_set(
        u.data,
        '$.roleNames', (
            select json_arrayagg(r.name)
            from roles r
            where json_contains(u.data, cast(r.role_id as json), '$.roleIds')
        )
    ) as data
from users u

Demo on DB Fiddle:

id data
1 {"name": "cat", "roleIds": [2, 3], "roleNames": ["Supervisor", "Provisioner"]}
2 {"name": "dog", "roleIds": [1, 4], "roleNames": ["Admin", "Operator"]}
3 {"name": "mouse", "roleIds": [5], "roleNames": ["Relief"]}

需要指出的是,MySQL 不保证元素在 json_arrayagg() 生成的数组中出现的顺序。这是我们必须接受的当前数据库版本的限制。