【Mysql】JSON 數據類型初探

從 MySQL 5.7.8 開始,MySQL 支持原生的 JSON 數據類型。
類似 varchar,設置 JSON 主要將字段的 type 是 json, 不能設置長度,可以是 NULL 但不能有默認值。

創建 JSON

CREATE TABLE test_json (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`category` JSON,
`tags` JSON,
PRIMARY KEY (`id`)
);

插入 JSON

-- 就是插入 json 格式的字符串,可以是對象的形式,也可以是數組的形式
INSERT INTO `test_json` (category, tags) VALUES ('{"id": 1, "name": "itplh.com"}', '[1, 2, 3]');
-- MySQL 也有專門的函數 JSON_OBJECT,JSON_ARRAY 生成 json 格式的數據
INSERT INTO `test_json` (category, tags) VALUES (JSON_OBJECT("id", 2, "name", "java.net"), JSON_ARRAY(1, 3, 5));

-- 更多生成 JSON 值的函數請參考: http://dev.mysql.com/doc/refman/5.7/en/json-creation-functions.html

查詢 JSON

-- 查詢 json 中的數據用 column->path 的形式,其中對象類型 path 這樣表示 .path, 而數組類型則是 *[index]
SELECT id, category->'$.id' AS categoryId, category->'$.name' AS categoryName, tags-'$[0]' AS tags1, tags->'$[2]' AS tags3 FROM test_json;
-- 可以看到對應字符串類型的 category->’$.name’ 中還包含着雙引號,這其實並不是想要的結果,可以用 JSON_UNQUOTE 函數將雙引號去掉
-- 從 MySQL 5.7.13 起也可以通過這個操作符 ->> 這個和 JSON_UNQUOTE 是等價的
SELECT id, category->'$.name' AS categoryName1, JSON_UNQUOTE(category->'$.name') AS categoryName2, category->>'$.name' AS categoryName3 FROM test_json;
-- 下面說下 JSON 作爲條件進行搜索。因爲 JSON 不同於字符串,所以如果用字符串和 JSON 字段比較,是不會相等的
SELECT * FROM test_json WHERE category = '{"id": 1, "name": "itplh.com"}';
-- 這時可以通過 CAST 將字符串轉成 JSON 的形式
SELECT * FROM test_json WHERE category = CAST('{"id": 1, "name": "itplh.com"}' AS JSON);
-- 通過 JSON 中的元素進行查詢, 對象型的查詢同樣可以通過 column->path
SELECT * FROM test_json WHERE category->'$.name' = 'itplh.com';
-- 上面有提到 column->path 形式從 select 中查詢出來的字符串是包含雙引號的,但作爲條件這裏其實沒什麼影響,-> 和 ->> 結果是一樣的
SELECT * FROM test_json WHERE category->>'$.name' = 'itplh.com';
-- 要特別注意的是,JSON 中的元素搜索是嚴格區分變量類型的,比如說整型和字符串是嚴格區分的
SELECT * FROM test_json WHERE category->'$.id' = '1';
SELECT * FROM test_json WHERE category->'$.id' = 1; -- 可以看到搜索字符串 1 和整型 1 的結果是不一樣的。

-- 除了用 column->path 的形式搜索,還可以用 JSON_CONTAINS 函數,
-- 但和 *column->path *的形式有點相反的是,JSON_CONTAINS 第二個參數是不接受整數的
-- 無論 json 元素是整型還是字符串,否則會出現這個錯誤
SELECT * FROM test_json WHERE JSON_CONTAINS(category, 1, '$.id'); -- 錯誤代碼: 3146 Invalid DATA TYPE FOR JSON DATA IN argument 2 TO FUNCTION JSON_CONTAINS; a JSON STRING OR JSON TYPE IS required.
-- JSON_CONTAINS 第二個參數必須是要字符串 1
SELECT * FROM test_json WHERE JSON_CONTAINS(category, '1', '$.id');
-- 對於數組類型的 JSON 的查詢,比如說 tags 中包含有 2 的數據,同樣要用 JSON_CONTAINS 函數,同樣第二個參數也需要是字符串
SELECT * FROM test_json WHERE JSON_CONTAINS(tags, '2');

-- 更多搜索 JSON 值的函數請參考:https://dev.mysql.com/doc/refman/5.7/en/json-function-reference.html

更新 JSON

-- 如果是整個 json 更新的話,和插入時類似的。
UPDATE test_json SET tags = '[1, 3, 4]' WHERE id = 1;
SELECT * FROM test_json;
-- 但如果要更新 JSON 下的元素,MySQL 並不支持 column->path 的形式
UPDATE test_json SET category->'$.name' = 'test_json', tags-'$[0]' = 2 WHERE id = 1; -- 錯誤代碼: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '->'$.name' = 'test_json', tags-'$[0]' = 2 WHERE id = 1' at line 1

-- 則可能要用到以下幾個函數
-- JSON_INSERT() 插入新值,但不會覆蓋已經存在的值
UPDATE test_json SET category = JSON_INSERT(category, '$.name', 'test_json', '$.url', 'www.itplh.com') WHERE id = 1;
SELECT * FROM test_json; -- 可以看到 name 沒有被修改,但新元素 url 已經添加進去
-- JSON_SET() 插入新值,並覆蓋已經存在的值
UPDATE test_json SET category = JSON_SET(category, '$.host', 'www.itplh.com', '$.url', 'http://www.itplh.com') WHERE id = 1;
SELECT * FROM test_json; -- 可以看到 host 已經插入,url 已經被修改
-- JSON_REPLACE() 只替換存在的值
UPDATE test_json SET category = JSON_REPLACE(category, '$.name', 'java', '$.url', 'http://www.java.net') WHERE id = 1;
SELECT * FROM test_json; -- 可以看到 name 已經被替換,url 不存在被忽略。
-- JSON_REMOVE() 刪除 JSON 元素
UPDATE test_json SET category = JSON_REMOVE(category, '$.url', '$.host') WHERE id = 1;
SELECT * FROM test_json;
-- 更多函數請參考:http://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html
發佈了97 篇原創文章 · 獲贊 44 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章