Mysql

是否可以在 MySQL 中按值刪除 JSON 數組元素?

  • June 9, 2021

在 MySQL 中,可以通過索引刪除數組元素:

SELECT JSON_REMOVE('["a", "b", "c"]', '$[1]') `result`;
+------------+
| result     |
+------------+
| ["a", "c"] |
+------------+

是否可以按值刪除 - 在這種情況下是匹配字元串的元素"b"

根據文件,可以通過找到索引JSON_SEARCH然後將其傳遞給JSON_REMOVE,但是,我想知道是否有表達式/函式可以在單個函式中執行此操作。

在撰寫本文時,MySQL 沒有專門的 JSON 函式來允許您按其值刪除 JSON 數組元素。您必須使用任何可用的函式來提出自定義表達式來實現您的目標。根據要求,您甚至可能想要創建自定義函式。

更具體地說,如果要求是刪除第一次出現的值,那麼一種方法是這樣的:

SET @value := 'b';

SELECT
 j.j AS before_remove
, JSON_REMOVE(
   j.j
 , JSON_UNQUOTE(
     JSON_SEARCH(
       j.j
     , 'one'
     , @value
     )
   )
 ) AS after_remove
FROM
 (SELECT '["a", "b", "c", "b"]') AS j (j)
;

回報:

JSON_SEARCH返回找到的值的帶引號的路徑("$[1]"在這種情況下),JSON_UNQUOTE刪除引號(yielding $[1]),然後可以將路徑饋送到JSON_REMOVE.

如果要刪除任意出現的 value,則表達式會變得更加複雜:

SET @value := 'b';
SET @occurrence := 2;

SELECT
 j.j AS before_remove
, JSON_REMOVE(
   j.j
 , JSON_UNQUOTE(
     JSON_EXTRACT(
       JSON_SEARCH(
         j.j
       , 'all'
       , @value
       )
     , CONCAT('$[', @occurrence - 1, ']')
     )
   )
 ) AS after_remove
FROM
 (SELECT '["a", "b", "c", "b"]') AS j (j)
;

輸出:

在這種情況下,根據找到的條目數,JSON_SEARCH可能會返回 JSON 路徑數組而不是單個路徑。因此,在應用 之前JSON_UNQUOTE,我們需要從與所需匹配項匹配的數組中提取特定路徑,我們可以使用JSON_EXTRACT. 該CONCAT表達式返回對應的路徑JSON_EXTRACT(然後我們得到一個使用的路徑JSON_REMOVE——是的,我知道,這有點令人困惑)。

最後,為了能夠刪除所有出現的事件,您需要遍歷由返回的路徑數組的結果,JSON_SEARCH或者按順序執行JSON_REMOVE每個路徑,或者以某種方式建構和評估包括所有路徑的單個動態JSON_REMOVE表達式。無論哪種方式,您都需要在自定義創建的函式中執行此操作。

或者,您可以嘗試以基於集合的方式解決此問題,例如使用JSON_TABLE函式將路徑數組 - 輸出JSON_SEARCH- 轉換為行集合,每行一條路徑,然後在集合上使用遞歸 CTE,應用每條路徑一個一個地得到最後的結果作為最終的 JSON。

選項在那裡,我將解決方案留給讀者作為練習。我只會補充一點,上面的兩個查詢都可以在 db<>fiddle線上獲得。

引用自:https://dba.stackexchange.com/questions/293864