[英]MySQL JSON_SET() to work with empty arrays
我有一張這樣的表:
CREATE TABLE `test` (
`id` int(11) NOT NULL,
`settings` json NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
INSERT INTO `test` (`id`, `settings`) VALUES
('1', '{\"foo\": {\"bar\": 1}}'),
('2', '{\"foobar\": 2}'),
('3', '[]');
我想在一行中添加一個新設置,所以我嘗試了JSON_SET :
SELECT *, JSON_SET(settings, '$.newFoo', 10) FROM test;
如您所見,它不適用於第 3 行。預期結果當然與第 4 行相同; []
是在 php 中對空數組進行 json 編碼的結果,如果該項目沒有任何設置。
可以進行適用於所有情況的單個查詢嗎?
PS:我需要做的是一個UPDATE,即UPDATE test SET settings=JSON_SET(...) WHERE id=?;
對JSON_SET
的調用JSON_SET
預期運行的原因是,處理 JSON 數組所需的語法與處理單個 JSON 所需的語法不同。 考慮以下查詢,它將 JSON 添加到空數組:
SELECT JSON_SET('[]', '$[0]', '{"newFoo": 10}') AS output;
這打印:
["{\"newFoo\": 10}"]
所以JSON_SET
函數似乎有兩種行為。 在正確操作 JSON 時,它可以插入新密鑰或更新已存在的密鑰。 在對數組進行操作時,它可以插入/更新數組的元素,這些元素可能是整個 JSON 對象。
這也難倒了我很長一段時間,但嘗試使用 JSON_ARRAY() 而不是雙括號符號“[]”。 例如:
INSERT INTO `test` (`id`, `settings`) VALUES
('1', '{\"foo\": {\"bar\": 1}}'),
('2', '{\"foobar\": 2}'),
('3', JSON_ARRAY());
您可以使用CASE .. WHEN
條件運算符在單個查詢中處理此問題。 此外,由於您的settings
數據類型是Json
,您需要先將它Cast()
到字符串 (Char) 以檢查[]
:
SELECT *,
CASE WHEN CAST(settings AS CHAR) = '[]'
THEN JSON_SET('{}', '$.newFoo', 10)
ELSE JSON_SET(settings, '$.newFoo', 10)
END AS modified_settings
FROM test;
相同的Update
查詢如下:
UPDATE test
SET settings = CASE WHEN CAST(settings AS CHAR) = '[]'
THEN JSON_SET('{}', '$.newFoo', 10)
ELSE JSON_SET(settings, '$.newFoo', 10)
END
我通過始終將值存儲為對象而不是數組來解決,在 PHP 中您需要向json_encode
函數添加一個標志:
json_encode($value, JSON_FORCE_OBJECT)
或者,作為替代,使字段可以為空並使用COALESCE :
SELECT *, JSON_SET(COALESCE(settings, '{}'), '$.newFoo', 10) FROM test;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.