Đây là một cách cực kỳ phức tạp để thực hiện việc này trong MySQL, sử dụng JSON_TABLE
để chuyển đổi bản cập nhật và các giá trị JSON gốc thành các cột, hợp nhất các cột bằng cách sử dụng FULL JOIN
(được mô phỏng) và sau đó tạo lại giá trị JSON đầu ra bằng cách sử dụng JSON_OBJECT
và JSON_ARRAYAGG
; cuối cùng sử dụng nó để cập nhật bảng gốc:
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
Đầu ra:
[
{
"text": "substance_name_183",
"substanceId": 183
},
{
"text": "substance_name_184",
"substanceId": 184
},
{
"text": "substance_name_182_new",
"substanceId": 182
}
]
Lưu ý rằng điều này giả sử bạn sử dụng một id
duy nhất giá trị để phân biệt các hàng trong bảng của bạn. Nếu bạn sử dụng thứ gì đó khác, bạn sẽ cần hoán đổi thứ đó trong nơi id
được sử dụng trong truy vấn trên.