是否可以在 MySQL 中按值刪除 JSON 數組元素?
在 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線上獲得。