我有用于存储文档的JSON列。我想在此列上执行原子更新。
例如值:
[{"substanceId": 182, "text": "substance_name_182"}, {"substanceId": 183, "text": "substance_name_183"}]
和更新
[{"substanceId": 182, "text": "substance_name_182_new"}, {"substanceId": 184, "text": "substance_name_184"}]
我希望得到这个:
[{"substanceId": 182, "text": "substance_name_182_new"}, {"substanceId": 183, "text": "substance_name_183"} {"substanceId": 184, "text": "substance_name_184"}}]
JSON_MERGE_PATCH
或JSON_MERGE_PRESERVE
都不允许我直接实现。 JSON_MERGE_PATCH
不知道substanceId
是文档的ID。有什么方法可以在MySQL端实现它吗?我可以在客户端执行此操作(首先获取值,然后修改并更新回去),但这是不得已的方法,首先我要更新很多行,其中所有行都将由带有UPDATE
子句的WHERE
覆盖,因此MySQL的方式会更方便。在客户端进行安全操作时,我必须锁定许多行以进行更新。
例如查询:
SELECT JSON_MERGE_PATCH(
'[{"substanceId": 182, "text": "substance_name_182"}, {"substanceId": 183, "text": "substance_name_183"}]',
'[{"substanceId": 182, "text": "substance_name_182_new"}, {"substanceId": 184, "text": "substance_name_184"}]'
) v;
结果
[{"text": "substance_name_182_new", "substanceId": 182}, {"text": "substance_name_184", "substanceId": 184}]
[这是在MySQL中执行此操作的一种令人费解的方法,使用JSON_TABLE
将更新和原始JSON值转换为列,使用(模拟的)JSON_TABLE
合并列,然后使用重新创建输出JSON值FULL JOIN
和JSON_OBJECT
;最后使用它来更新原始表:
JSON_OBJECT
输出:
JSON_ARRAYAGG
JSON_ARRAYAGG
注意,这假设您使用唯一的WITH upd AS (
SELECT *
FROM JSON_TABLE('[{"substanceId": 182, "text": "substance_name_182_new"}, {"substanceId": 184, "text": "substance_name_184"}]',
'$[*]' COLUMNS (
substanceId INT PATH '$.substanceId',
txt VARCHAR (100) PATH '$.text')
) jt
CROSS JOIN (SELECT DISTINCT id
FROM test) t
),
cur AS (
SELECT id, substanceId, txt
FROM test
JOIN JSON_TABLE(test.j,
'$[*]' COLUMNS (
substanceId INT PATH '$.substanceId',
txt VARCHAR (100) PATH '$.text')
) jt
),
allv AS (
SELECT COALESCE(upd.id, cur.id) AS id,
COALESCE(upd.substanceId, cur.substanceId) AS substanceId,
COALESCE(upd.txt, cur.txt) AS txt
FROM upd
LEFT JOIN cur ON cur.substanceId = upd.substanceId
UNION ALL
SELECT COALESCE(upd.id, cur.id) AS id,
COALESCE(upd.substanceId, cur.substanceId) AS substanceId,
COALESCE(upd.txt, cur.txt) AS txt
FROM upd
RIGHT JOIN cur ON cur.substanceId = upd.substanceId
),
obj AS (
SELECT DISTINCT id, JSON_OBJECT('substanceId', substanceId, 'text', txt) AS o
FROM allv
),
arr AS (
SELECT id, JSON_ARRAYAGG(o) AS a
FROM obj
GROUP BY id
)
UPDATE test
JOIN arr ON test.id = arr.id
SET test.j = arr.a
;
SELECT JSON_PRETTY(j)
FROM test
值来区分表中的行。如果您使用其他内容,则需要在上面的查询中使用[
{
"text": "substance_name_183",
"substanceId": 183
},
{
"text": "substance_name_184",
"substanceId": 184
},
{
"text": "substance_name_182_new",
"substanceId": 182
}
]
的地方进行交换。