本節中的函數會對 JSON 值執行搜尋或比較運算,以便從中擷取資料、報告資料是否存在於其中的某個位置,或報告資料在其中的路徑。此處也會記錄 MEMBER OF() 運算子。
JSON_CONTAINS(target,candidate[,path])透過傳回 1 或 0 來表示指定的
candidateJSON 文件是否包含在targetJSON 文件中,或者如果提供path引數,則表示是否在目標內的特定路徑找到候選項目。如果任何引數為NULL,或路徑引數未識別目標文件的區段,則傳回NULL。如果target或candidate不是有效的 JSON 文件,或者如果path引數不是有效的路徑表達式或包含*或**萬用字元,則會發生錯誤。若要僅檢查路徑上是否有任何資料存在,請改用
JSON_CONTAINS_PATH()。下列規則定義包含關係
當候選純量和目標純量可以比較且相等時,候選純量會包含在目標純量中。如果兩個純量值具有相同的
JSON_TYPE()類型,則可以比較它們,但INTEGER和DECIMAL類型的值也可以彼此比較。如果候選陣列中的每個元素都包含在目標陣列的某個元素中,則候選陣列會包含在目標陣列中。
如果候選非陣列包含在目標陣列的某個元素中,則候選非陣列會包含在目標陣列中。
如果候選物件中每個索引鍵在目標中都有同名的索引鍵,且與候選索引鍵關聯的值包含在與目標索引鍵關聯的值中,則候選物件會包含在目標物件中。
否則,候選值不會包含在目標文件中。
使用
JSON_CONTAINS()在InnoDB表格上執行的查詢可以使用多值索引進行最佳化;如需更多資訊,請參閱多值索引。mysql> SET @j = '{"a": 1, "b": 2, "c": {"d": 4}}'; mysql> SET @j2 = '1'; mysql> SELECT JSON_CONTAINS(@j, @j2, '$.a'); +-------------------------------+ | JSON_CONTAINS(@j, @j2, '$.a') | +-------------------------------+ | 1 | +-------------------------------+ mysql> SELECT JSON_CONTAINS(@j, @j2, '$.b'); +-------------------------------+ | JSON_CONTAINS(@j, @j2, '$.b') | +-------------------------------+ | 0 | +-------------------------------+ mysql> SET @j2 = '{"d": 4}'; mysql> SELECT JSON_CONTAINS(@j, @j2, '$.a'); +-------------------------------+ | JSON_CONTAINS(@j, @j2, '$.a') | +-------------------------------+ | 0 | +-------------------------------+ mysql> SELECT JSON_CONTAINS(@j, @j2, '$.c'); +-------------------------------+ | JSON_CONTAINS(@j, @j2, '$.c') | +-------------------------------+ | 1 | +-------------------------------+JSON_CONTAINS_PATH(json_doc,one_or_all,path[,path] ...)傳回 0 或 1,以表示 JSON 文件是否在給定的路徑或多個路徑包含資料。如果任何引數為
NULL,則傳回NULL。如果json_doc引數不是有效的 JSON 文件,任何path引數不是有效的路徑表達式,或者one_or_all不是'one'或'all',則會發生錯誤。若要檢查路徑上是否有特定值,請改用
JSON_CONTAINS()。如果文件中沒有指定的路徑存在,則傳回值為 0。否則,傳回值取決於
one_or_all引數'one':如果文件中至少存在一個路徑,則為 1,否則為 0。'all':如果文件中存在所有路徑,則為 1,否則為 0。
mysql> SET @j = '{"a": 1, "b": 2, "c": {"d": 4}}'; mysql> SELECT JSON_CONTAINS_PATH(@j, 'one', '$.a', '$.e'); +---------------------------------------------+ | JSON_CONTAINS_PATH(@j, 'one', '$.a', '$.e') | +---------------------------------------------+ | 1 | +---------------------------------------------+ mysql> SELECT JSON_CONTAINS_PATH(@j, 'all', '$.a', '$.e'); +---------------------------------------------+ | JSON_CONTAINS_PATH(@j, 'all', '$.a', '$.e') | +---------------------------------------------+ | 0 | +---------------------------------------------+ mysql> SELECT JSON_CONTAINS_PATH(@j, 'one', '$.c.d'); +----------------------------------------+ | JSON_CONTAINS_PATH(@j, 'one', '$.c.d') | +----------------------------------------+ | 1 | +----------------------------------------+ mysql> SELECT JSON_CONTAINS_PATH(@j, 'one', '$.a.d'); +----------------------------------------+ | JSON_CONTAINS_PATH(@j, 'one', '$.a.d') | +----------------------------------------+ | 0 | +----------------------------------------+JSON_EXTRACT(json_doc,path[,path] ...)從 JSON 文件傳回資料,該資料是從
path引數比對的文件部分選取的。如果任何引數為NULL,或沒有任何路徑在文件中找到值,則傳回NULL。如果json_doc引數不是有效的 JSON 文件,或任何path引數不是有效的路徑表達式,則會發生錯誤。傳回值包含所有符合
path引數的值。如果這些引數可能會傳回多個值,則符合的值會自動包裝成陣列,其順序對應於產生這些值的路徑。否則,傳回值會是單一符合的值。mysql> SELECT JSON_EXTRACT('[10, 20, [30, 40]]', '$[1]'); +--------------------------------------------+ | JSON_EXTRACT('[10, 20, [30, 40]]', '$[1]') | +--------------------------------------------+ | 20 | +--------------------------------------------+ mysql> SELECT JSON_EXTRACT('[10, 20, [30, 40]]', '$[1]', '$[0]'); +----------------------------------------------------+ | JSON_EXTRACT('[10, 20, [30, 40]]', '$[1]', '$[0]') | +----------------------------------------------------+ | [20, 10] | +----------------------------------------------------+ mysql> SELECT JSON_EXTRACT('[10, 20, [30, 40]]', '$[2][*]'); +-----------------------------------------------+ | JSON_EXTRACT('[10, 20, [30, 40]]', '$[2][*]') | +-----------------------------------------------+ | [30, 40] | +-----------------------------------------------+MySQL 支援
->運算子,作為此函數的簡寫,用於帶有 2 個引數的情況,其中左側是JSON資料欄識別符 (而非運算式),右側是要在資料欄中比對的 JSON 路徑。當
->運算子與兩個引數一起使用時,它會作為JSON_EXTRACT()函數的別名,左側為資料欄識別符,右側為 JSON 路徑 (字串常值),並針對 JSON 文件 (資料欄值) 進行評估。您可以在 SQL 陳述式中任何出現資料欄參照的位置使用此類運算式。這裡顯示的兩個
SELECT陳述式會產生相同的輸出mysql> SELECT c, JSON_EXTRACT(c, "$.id"), g > FROM jemp > WHERE JSON_EXTRACT(c, "$.id") > 1 > ORDER BY JSON_EXTRACT(c, "$.name"); +-------------------------------+-----------+------+ | c | c->"$.id" | g | +-------------------------------+-----------+------+ | {"id": "3", "name": "Barney"} | "3" | 3 | | {"id": "4", "name": "Betty"} | "4" | 4 | | {"id": "2", "name": "Wilma"} | "2" | 2 | +-------------------------------+-----------+------+ 3 rows in set (0.00 sec) mysql> SELECT c, c->"$.id", g > FROM jemp > WHERE c->"$.id" > 1 > ORDER BY c->"$.name"; +-------------------------------+-----------+------+ | c | c->"$.id" | g | +-------------------------------+-----------+------+ | {"id": "3", "name": "Barney"} | "3" | 3 | | {"id": "4", "name": "Betty"} | "4" | 4 | | {"id": "2", "name": "Wilma"} | "2" | 2 | +-------------------------------+-----------+------+ 3 rows in set (0.00 sec)此功能不限於
SELECT,如下所示mysql> ALTER TABLE jemp ADD COLUMN n INT; Query OK, 0 rows affected (0.68 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> UPDATE jemp SET n=1 WHERE c->"$.id" = "4"; Query OK, 1 row affected (0.04 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> SELECT c, c->"$.id", g, n > FROM jemp > WHERE JSON_EXTRACT(c, "$.id") > 1 > ORDER BY c->"$.name"; +-------------------------------+-----------+------+------+ | c | c->"$.id" | g | n | +-------------------------------+-----------+------+------+ | {"id": "3", "name": "Barney"} | "3" | 3 | NULL | | {"id": "4", "name": "Betty"} | "4" | 4 | 1 | | {"id": "2", "name": "Wilma"} | "2" | 2 | NULL | +-------------------------------+-----------+------+------+ 3 rows in set (0.00 sec) mysql> DELETE FROM jemp WHERE c->"$.id" = "4"; Query OK, 1 row affected (0.04 sec) mysql> SELECT c, c->"$.id", g, n > FROM jemp > WHERE JSON_EXTRACT(c, "$.id") > 1 > ORDER BY c->"$.name"; +-------------------------------+-----------+------+------+ | c | c->"$.id" | g | n | +-------------------------------+-----------+------+------+ | {"id": "3", "name": "Barney"} | "3" | 3 | NULL | | {"id": "2", "name": "Wilma"} | "2" | 2 | NULL | +-------------------------------+-----------+------+------+ 2 rows in set (0.00 sec)(如需用於建立和填入剛剛顯示的資料表的陳述式,請參閱 為 JSON 資料欄索引提供索引的產生資料欄。)
這也適用於 JSON 陣列值,如下所示
mysql> CREATE TABLE tj10 (a JSON, b INT); Query OK, 0 rows affected (0.26 sec) mysql> INSERT INTO tj10 > VALUES ("[3,10,5,17,44]", 33), ("[3,10,5,17,[22,44,66]]", 0); Query OK, 1 row affected (0.04 sec) mysql> SELECT a->"$[4]" FROM tj10; +--------------+ | a->"$[4]" | +--------------+ | 44 | | [22, 44, 66] | +--------------+ 2 rows in set (0.00 sec) mysql> SELECT * FROM tj10 WHERE a->"$[0]" = 3; +------------------------------+------+ | a | b | +------------------------------+------+ | [3, 10, 5, 17, 44] | 33 | | [3, 10, 5, 17, [22, 44, 66]] | 0 | +------------------------------+------+ 2 rows in set (0.00 sec)支援巢狀陣列。如果目標 JSON 文件中找不到相符的鍵,則使用
->的運算式會評估為NULL,如下所示mysql> SELECT * FROM tj10 WHERE a->"$[4][1]" IS NOT NULL; +------------------------------+------+ | a | b | +------------------------------+------+ | [3, 10, 5, 17, [22, 44, 66]] | 0 | +------------------------------+------+ mysql> SELECT a->"$[4][1]" FROM tj10; +--------------+ | a->"$[4][1]" | +--------------+ | NULL | | 44 | +--------------+ 2 rows in set (0.00 sec)這與使用
JSON_EXTRACT()時在此類情況下看到的行為相同mysql> SELECT JSON_EXTRACT(a, "$[4][1]") FROM tj10; +----------------------------+ | JSON_EXTRACT(a, "$[4][1]") | +----------------------------+ | NULL | | 44 | +----------------------------+ 2 rows in set (0.00 sec)這是一個改良的、取消引號的擷取運算子。
->運算子僅擷取值,而->>運算子還會取消擷取結果的引號。換句話說,給定JSON資料欄值column和路徑運算式path(字串常值),以下三個運算式會傳回相同的值JSON_UNQUOTE(column->path)column->>path
在允許使用
JSON_UNQUOTE(JSON_EXTRACT())的任何位置,都可以使用->>運算子。這包括 (但不限於)SELECT清單、WHERE和HAVING子句,以及ORDER BY和GROUP BY子句。接下來的幾個陳述式示範了 mysql 用戶端中
->>運算子與其他運算式的一些等效性mysql> SELECT * FROM jemp WHERE g > 2; +-------------------------------+------+ | c | g | +-------------------------------+------+ | {"id": "3", "name": "Barney"} | 3 | | {"id": "4", "name": "Betty"} | 4 | +-------------------------------+------+ 2 rows in set (0.01 sec) mysql> SELECT c->'$.name' AS name -> FROM jemp WHERE g > 2; +----------+ | name | +----------+ | "Barney" | | "Betty" | +----------+ 2 rows in set (0.00 sec) mysql> SELECT JSON_UNQUOTE(c->'$.name') AS name -> FROM jemp WHERE g > 2; +--------+ | name | +--------+ | Barney | | Betty | +--------+ 2 rows in set (0.00 sec) mysql> SELECT c->>'$.name' AS name -> FROM jemp WHERE g > 2; +--------+ | name | +--------+ | Barney | | Betty | +--------+ 2 rows in set (0.00 sec)如需用於建立和填入剛剛顯示的範例集中
jemp資料表的 SQL 陳述式,請參閱 為 JSON 資料欄索引提供索引的產生資料欄。此運算子也可以與 JSON 陣列搭配使用,如下所示
mysql> CREATE TABLE tj10 (a JSON, b INT); Query OK, 0 rows affected (0.26 sec) mysql> INSERT INTO tj10 VALUES -> ('[3,10,5,"x",44]', 33), -> ('[3,10,5,17,[22,"y",66]]', 0); Query OK, 2 rows affected (0.04 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> SELECT a->"$[3]", a->"$[4][1]" FROM tj10; +-----------+--------------+ | a->"$[3]" | a->"$[4][1]" | +-----------+--------------+ | "x" | NULL | | 17 | "y" | +-----------+--------------+ 2 rows in set (0.00 sec) mysql> SELECT a->>"$[3]", a->>"$[4][1]" FROM tj10; +------------+---------------+ | a->>"$[3]" | a->>"$[4][1]" | +------------+---------------+ | x | NULL | | 17 | y | +------------+---------------+ 2 rows in set (0.00 sec)與
->相同,->>運算子始終會在EXPLAIN的輸出中展開,如下列範例所示mysql> EXPLAIN SELECT c->>'$.name' AS name -> FROM jemp WHERE g > 2\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: jemp partitions: NULL type: range possible_keys: i key: i key_len: 5 ref: NULL rows: 2 filtered: 100.00 Extra: Using where 1 row in set, 1 warning (0.00 sec) mysql> SHOW WARNINGS\G *************************** 1. row *************************** Level: Note Code: 1003 Message: /* select#1 */ select json_unquote(json_extract(`jtest`.`jemp`.`c`,'$.name')) AS `name` from `jtest`.`jemp` where (`jtest`.`jemp`.`g` > 2) 1 row in set (0.00 sec)這類似於 MySQL 在相同情況下展開
->運算子的方式。將 JSON 物件頂層值的鍵傳回為 JSON 陣列,或者,如果提供
path引數,則傳回選定路徑的頂層鍵。如果任何引數為NULL,json_doc引數不是物件,或path(如果提供) 找不到物件,則傳回NULL。如果json_doc引數不是有效的 JSON 文件,或path引數不是有效的路徑運算式,或包含*或**萬用字元,則會發生錯誤。如果選取的物件是空的,則結果陣列也是空的。如果頂層值具有巢狀子物件,則傳回值不包含這些子物件的鍵。
mysql> SELECT JSON_KEYS('{"a": 1, "b": {"c": 30}}'); +---------------------------------------+ | JSON_KEYS('{"a": 1, "b": {"c": 30}}') | +---------------------------------------+ | ["a", "b"] | +---------------------------------------+ mysql> SELECT JSON_KEYS('{"a": 1, "b": {"c": 30}}', '$.b'); +----------------------------------------------+ | JSON_KEYS('{"a": 1, "b": {"c": 30}}', '$.b') | +----------------------------------------------+ | ["c"] | +----------------------------------------------+JSON_OVERLAPS(json_doc1,json_doc2)比較兩個 JSON 文件。如果兩個文件有任何共同的鍵值配對或陣列元素,則傳回 true (1)。如果兩個引數都是純量,則函數會執行簡單的相等性測試。如果任一引數為
NULL,則函數會傳回NULL。此函數作為
JSON_CONTAINS()的對應函數,它要求所搜尋的陣列的所有元素都必須存在於所搜尋的陣列中。因此,JSON_CONTAINS()會對搜尋鍵執行AND運算,而JSON_OVERLAPS()則會執行OR運算。可以使用多值索引來最佳化在
WHERE子句中使用JSON_OVERLAPS()對InnoDB資料表的 JSON 資料欄執行的查詢。多值索引提供詳細資訊和範例。比較兩個陣列時,如果它們共同擁有一個或多個陣列元素,則
JSON_OVERLAPS()會傳回 true,否則會傳回 falsemysql> SELECT JSON_OVERLAPS("[1,3,5,7]", "[2,5,7]"); +---------------------------------------+ | JSON_OVERLAPS("[1,3,5,7]", "[2,5,7]") | +---------------------------------------+ | 1 | +---------------------------------------+ 1 row in set (0.00 sec) mysql> SELECT JSON_OVERLAPS("[1,3,5,7]", "[2,6,7]"); +---------------------------------------+ | JSON_OVERLAPS("[1,3,5,7]", "[2,6,7]") | +---------------------------------------+ | 1 | +---------------------------------------+ 1 row in set (0.00 sec) mysql> SELECT JSON_OVERLAPS("[1,3,5,7]", "[2,6,8]"); +---------------------------------------+ | JSON_OVERLAPS("[1,3,5,7]", "[2,6,8]") | +---------------------------------------+ | 0 | +---------------------------------------+ 1 row in set (0.00 sec)部分比對會被視為不比對,如下所示
mysql> SELECT JSON_OVERLAPS('[[1,2],[3,4],5]', '[1,[2,3],[4,5]]'); +-----------------------------------------------------+ | JSON_OVERLAPS('[[1,2],[3,4],5]', '[1,[2,3],[4,5]]') | +-----------------------------------------------------+ | 0 | +-----------------------------------------------------+ 1 row in set (0.00 sec)比較物件時,如果它們至少有一個共同的鍵值配對,則結果為 true。
mysql> SELECT JSON_OVERLAPS('{"a":1,"b":10,"d":10}', '{"c":1,"e":10,"f":1,"d":10}'); +-----------------------------------------------------------------------+ | JSON_OVERLAPS('{"a":1,"b":10,"d":10}', '{"c":1,"e":10,"f":1,"d":10}') | +-----------------------------------------------------------------------+ | 1 | +-----------------------------------------------------------------------+ 1 row in set (0.00 sec) mysql> SELECT JSON_OVERLAPS('{"a":1,"b":10,"d":10}', '{"a":5,"e":10,"f":1,"d":20}'); +-----------------------------------------------------------------------+ | JSON_OVERLAPS('{"a":1,"b":10,"d":10}', '{"a":5,"e":10,"f":1,"d":20}') | +-----------------------------------------------------------------------+ | 0 | +-----------------------------------------------------------------------+ 1 row in set (0.00 sec)如果將兩個純量用作函數的引數,則
JSON_OVERLAPS()會執行簡單的相等性測試mysql> SELECT JSON_OVERLAPS('5', '5'); +-------------------------+ | JSON_OVERLAPS('5', '5') | +-------------------------+ | 1 | +-------------------------+ 1 row in set (0.00 sec) mysql> SELECT JSON_OVERLAPS('5', '6'); +-------------------------+ | JSON_OVERLAPS('5', '6') | +-------------------------+ | 0 | +-------------------------+ 1 row in set (0.00 sec)當將純量與陣列比較時,
JSON_OVERLAPS()會嘗試將純量視為陣列元素。在此範例中,第二個引數6會解譯為[6],如下所示mysql> SELECT JSON_OVERLAPS('[4,5,6,7]', '6'); +---------------------------------+ | JSON_OVERLAPS('[4,5,6,7]', '6') | +---------------------------------+ | 1 | +---------------------------------+ 1 row in set (0.00 sec)此函數不會執行類型轉換
mysql> SELECT JSON_OVERLAPS('[4,5,"6",7]', '6'); +-----------------------------------+ | JSON_OVERLAPS('[4,5,"6",7]', '6') | +-----------------------------------+ | 0 | +-----------------------------------+ 1 row in set (0.00 sec) mysql> SELECT JSON_OVERLAPS('[4,5,6,7]', '"6"'); +-----------------------------------+ | JSON_OVERLAPS('[4,5,6,7]', '"6"') | +-----------------------------------+ | 0 | +-----------------------------------+ 1 row in set (0.00 sec)JSON_SEARCH(json_doc,one_or_all,search_str[,escape_char[,path] ...])傳回 JSON 文件中指定字串的路徑。如果任何
json_doc、search_str或path引數為NULL;文件中不存在path;或找不到search_str,則傳回NULL。如果json_doc引數不是有效的 JSON 文件,任何path引數不是有效的路徑運算式,one_or_all不是'one'或'all',或escape_char不是常數運算式,則會發生錯誤。one_or_all引數會依如下方式影響搜尋'one': 搜尋會在第一個比對之後終止,並傳回一個路徑字串。未定義哪個比對被視為第一個。'all': 搜尋會傳回所有相符的路徑字串,這樣就不會包含重複的路徑。如果有多個字串,則會將它們自動包裝為陣列。陣列元素的順序未定義。
在
search_str搜尋字串引數中,%和_字元的運作方式與LIKE運算子相同:%會比對任何數量的字元 (包括零個字元),而_則會比對一個字元。若要在搜尋字串中指定常值
%或_字元,請在其前面加上逸出字元。如果缺少escape_char引數或為NULL,則預設值為\。否則,escape_char必須是空值或一個字元的常數。如需比對和逸出字元行為的詳細資訊,請參閱 第 14.8.1 節「字串比較函數和運算子」中
LIKE的描述。對於逸出字元處理,與LIKE行為的不同之處在於JSON_SEARCH()的逸出字元必須在編譯時評估為常數,而不僅僅是在執行時評估。例如,如果在預先準備好的陳述式中使用JSON_SEARCH(),並且使用?參數提供escape_char引數,則參數值在執行時可能是常數,但在編譯時則不是。mysql> SET @j = '["abc", [{"k": "10"}, "def"], {"x":"abc"}, {"y":"bcd"}]'; mysql> SELECT JSON_SEARCH(@j, 'one', 'abc'); +-------------------------------+ | JSON_SEARCH(@j, 'one', 'abc') | +-------------------------------+ | "$[0]" | +-------------------------------+ mysql> SELECT JSON_SEARCH(@j, 'all', 'abc'); +-------------------------------+ | JSON_SEARCH(@j, 'all', 'abc') | +-------------------------------+ | ["$[0]", "$[2].x"] | +-------------------------------+ mysql> SELECT JSON_SEARCH(@j, 'all', 'ghi'); +-------------------------------+ | JSON_SEARCH(@j, 'all', 'ghi') | +-------------------------------+ | NULL | +-------------------------------+ mysql> SELECT JSON_SEARCH(@j, 'all', '10'); +------------------------------+ | JSON_SEARCH(@j, 'all', '10') | +------------------------------+ | "$[1][0].k" | +------------------------------+ mysql> SELECT JSON_SEARCH(@j, 'all', '10', NULL, '$'); +-----------------------------------------+ | JSON_SEARCH(@j, 'all', '10', NULL, '$') | +-----------------------------------------+ | "$[1][0].k" | +-----------------------------------------+ mysql> SELECT JSON_SEARCH(@j, 'all', '10', NULL, '$[*]'); +--------------------------------------------+ | JSON_SEARCH(@j, 'all', '10', NULL, '$[*]') | +--------------------------------------------+ | "$[1][0].k" | +--------------------------------------------+ mysql> SELECT JSON_SEARCH(@j, 'all', '10', NULL, '$**.k'); +---------------------------------------------+ | JSON_SEARCH(@j, 'all', '10', NULL, '$**.k') | +---------------------------------------------+ | "$[1][0].k" | +---------------------------------------------+ mysql> SELECT JSON_SEARCH(@j, 'all', '10', NULL, '$[*][0].k'); +-------------------------------------------------+ | JSON_SEARCH(@j, 'all', '10', NULL, '$[*][0].k') | +-------------------------------------------------+ | "$[1][0].k" | +-------------------------------------------------+ mysql> SELECT JSON_SEARCH(@j, 'all', '10', NULL, '$[1]'); +--------------------------------------------+ | JSON_SEARCH(@j, 'all', '10', NULL, '$[1]') | +--------------------------------------------+ | "$[1][0].k" | +--------------------------------------------+ mysql> SELECT JSON_SEARCH(@j, 'all', '10', NULL, '$[1][0]'); +-----------------------------------------------+ | JSON_SEARCH(@j, 'all', '10', NULL, '$[1][0]') | +-----------------------------------------------+ | "$[1][0].k" | +-----------------------------------------------+ mysql> SELECT JSON_SEARCH(@j, 'all', 'abc', NULL, '$[2]'); +---------------------------------------------+ | JSON_SEARCH(@j, 'all', 'abc', NULL, '$[2]') | +---------------------------------------------+ | "$[2].x" | +---------------------------------------------+ mysql> SELECT JSON_SEARCH(@j, 'all', '%a%'); +-------------------------------+ | JSON_SEARCH(@j, 'all', '%a%') | +-------------------------------+ | ["$[0]", "$[2].x"] | +-------------------------------+ mysql> SELECT JSON_SEARCH(@j, 'all', '%b%'); +-------------------------------+ | JSON_SEARCH(@j, 'all', '%b%') | +-------------------------------+ | ["$[0]", "$[2].x", "$[3].y"] | +-------------------------------+ mysql> SELECT JSON_SEARCH(@j, 'all', '%b%', NULL, '$[0]'); +---------------------------------------------+ | JSON_SEARCH(@j, 'all', '%b%', NULL, '$[0]') | +---------------------------------------------+ | "$[0]" | +---------------------------------------------+ mysql> SELECT JSON_SEARCH(@j, 'all', '%b%', NULL, '$[2]'); +---------------------------------------------+ | JSON_SEARCH(@j, 'all', '%b%', NULL, '$[2]') | +---------------------------------------------+ | "$[2].x" | +---------------------------------------------+ mysql> SELECT JSON_SEARCH(@j, 'all', '%b%', NULL, '$[1]'); +---------------------------------------------+ | JSON_SEARCH(@j, 'all', '%b%', NULL, '$[1]') | +---------------------------------------------+ | NULL | +---------------------------------------------+ mysql> SELECT JSON_SEARCH(@j, 'all', '%b%', '', '$[1]'); +-------------------------------------------+ | JSON_SEARCH(@j, 'all', '%b%', '', '$[1]') | +-------------------------------------------+ | NULL | +-------------------------------------------+ mysql> SELECT JSON_SEARCH(@j, 'all', '%b%', '', '$[3]'); +-------------------------------------------+ | JSON_SEARCH(@j, 'all', '%b%', '', '$[3]') | +-------------------------------------------+ | "$[3].y" | +-------------------------------------------+如需 MySQL 支援的 JSON 路徑語法的詳細資訊 (包括管理萬用字元
*和**的規則),請參閱 JSON 路徑語法。從指定文件中給定路徑的 JSON 文件中擷取值,並傳回擷取的值,選擇性地將其轉換為所需的類型。完整語法如下所示
JSON_VALUE(json_doc, path [RETURNING type] [on_empty] [on_error]) on_empty: {NULL | ERROR | DEFAULT value} ON EMPTY on_error: {NULL | ERROR | DEFAULT value} ON ERRORjson_doc是有效的 JSON 文件。如果此為NULL,則函數會傳回NULL。path是指向文件中位置的 JSON 路徑。這必須是字串常值。type是下列其中一個資料類型剛列出的類型與
CAST()函數支援的 (非陣列) 類型相同。如果沒有使用
RETURNING子句指定,JSON_VALUE()函數的回傳類型為VARCHAR(512)。當回傳類型沒有指定字元集時,JSON_VALUE()使用utf8mb4和二進位排序規則,這會區分大小寫;如果為結果指定utf8mb4作為字元集,伺服器會使用此字元集的預設排序規則,該規則不區分大小寫。當指定路徑上的資料包含或解析為 JSON null 文字時,函數會傳回 SQL
NULL。如果指定
on_empty,則決定當在給定的路徑上找不到資料時,JSON_VALUE()的行為;此子句採用下列其中一個值NULL ON EMPTY:函數傳回NULL;這是預設的ON EMPTY行為。DEFAULT:傳回提供的valueON EMPTYvalue。值的類型必須與回傳類型相符。ERROR ON EMPTY:函數會拋出錯誤。
如果使用
on_error,則會採用下列其中一個值,並在發生錯誤時產生相應的結果,如下所示NULL ON ERROR:JSON_VALUE()會傳回NULL;如果沒有使用ON ERROR子句,這是預設行為。DEFAULT:這是傳回的值;其值必須與回傳類型相符。valueON ERRORERROR ON ERROR:會拋出錯誤。
如果使用
ON EMPTY,則必須在任何ON ERROR子句之前。以錯誤的順序指定它們會導致語法錯誤。錯誤處理。一般而言,
JSON_VALUE()處理錯誤的方式如下所有 JSON 輸入(文件和路徑)都會檢查其有效性。如果其中任何一個無效,則會拋出 SQL 錯誤,而不會觸發
ON ERROR子句。當發生下列任何事件時,就會觸發
ON ERROR嘗試擷取物件或陣列,例如從解析為 JSON 文件中多個位置的路徑所產生的物件或陣列
轉換錯誤,例如嘗試將
'asdf'轉換為UNSIGNED值值的截斷
即使指定了
NULL ON ERROR或DEFAULT ... ON ERROR,轉換錯誤始終會觸發警告。當來源 JSON 文件(
expr)在指定的位置(path)沒有資料時,會觸發ON EMPTY子句。
範例。此處顯示兩個簡單的範例
mysql> SELECT JSON_VALUE('{"fname": "Joe", "lname": "Palmer"}', '$.fname'); +--------------------------------------------------------------+ | JSON_VALUE('{"fname": "Joe", "lname": "Palmer"}', '$.fname') | +--------------------------------------------------------------+ | Joe | +--------------------------------------------------------------+ mysql> SELECT JSON_VALUE('{"item": "shoes", "price": "49.95"}', '$.price' -> RETURNING DECIMAL(4,2)) AS price; +-------+ | price | +-------+ | 49.95 | +-------+語句
SELECT JSON_VALUE(等同於下列語句json_doc,pathRETURNINGtype)SELECT CAST( JSON_UNQUOTE( JSON_EXTRACT(json_doc, path) ) AS type );JSON_VALUE()簡化了在 JSON 資料行上建立索引的方式,在許多情況下,不再需要在產生的資料行上建立索引。當建立具有JSON資料行的資料表t1時,可以透過在操作該資料行的JSON_VALUE()的表示式上建立索引來實現(路徑與該資料行的值相符),如下所示CREATE TABLE t1( j JSON, INDEX i1 ( (JSON_VALUE(j, '$.id' RETURNING UNSIGNED)) ) );下列
EXPLAIN輸出顯示,對t1的查詢使用WHERE子句中的索引表示式,因此使用了建立的索引mysql> EXPLAIN SELECT * FROM t1 -> WHERE JSON_VALUE(j, '$.id' RETURNING UNSIGNED) = 123\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: t1 partitions: NULL type: ref possible_keys: i1 key: i1 key_len: 9 ref: const rows: 1 filtered: 100.00 Extra: NULL這與建立在產生的資料行上具有索引的資料表
t2達到幾乎相同的效果(請參閱索引產生的資料行以提供 JSON 資料行索引),如下所示CREATE TABLE t2 ( j JSON, g INT GENERATED ALWAYS AS (j->"$.id"), INDEX i1 (g) );對此資料表執行查詢並參考產生的資料行的
EXPLAIN輸出顯示,索引的使用方式與先前對資料表t1進行查詢的方式相同mysql> EXPLAIN SELECT * FROM t2 WHERE g = 123\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: t2 partitions: NULL type: ref possible_keys: i1 key: i1 key_len: 5 ref: const rows: 1 filtered: 100.00 Extra: NULL有關使用產生的資料行上的索引對
JSON資料行進行間接索引的相關資訊,請參閱索引產生的資料行以提供 JSON 資料行索引。如果
value是json_array的元素,則傳回 true (1),否則傳回 false (0)。value必須是純量或 JSON 文件;如果它是純量,運算子會嘗試將其視為 JSON 陣列的元素。如果value或json_array是NULL,則函數會傳回NULL。在
InnoDB資料表的 JSON 資料行上使用MEMBER OF()的查詢可以在WHERE子句中使用多值索引進行最佳化。如需詳細資訊和範例,請參閱多值索引。簡單的純量會被視為陣列值,如下所示
mysql> SELECT 17 MEMBER OF('[23, "abc", 17, "ab", 10]'); +-------------------------------------------+ | 17 MEMBER OF('[23, "abc", 17, "ab", 10]') | +-------------------------------------------+ | 1 | +-------------------------------------------+ 1 row in set (0.00 sec) mysql> SELECT 'ab' MEMBER OF('[23, "abc", 17, "ab", 10]'); +---------------------------------------------+ | 'ab' MEMBER OF('[23, "abc", 17, "ab", 10]') | +---------------------------------------------+ | 1 | +---------------------------------------------+ 1 row in set (0.00 sec)陣列元素值的局部比對不會相符
mysql> SELECT 7 MEMBER OF('[23, "abc", 17, "ab", 10]'); +------------------------------------------+ | 7 MEMBER OF('[23, "abc", 17, "ab", 10]') | +------------------------------------------+ | 0 | +------------------------------------------+ 1 row in set (0.00 sec)mysql> SELECT 'a' MEMBER OF('[23, "abc", 17, "ab", 10]'); +--------------------------------------------+ | 'a' MEMBER OF('[23, "abc", 17, "ab", 10]') | +--------------------------------------------+ | 0 | +--------------------------------------------+ 1 row in set (0.00 sec)不會執行字串類型之間的轉換
mysql> SELECT -> 17 MEMBER OF('[23, "abc", "17", "ab", 10]'), -> "17" MEMBER OF('[23, "abc", 17, "ab", 10]')\G *************************** 1. row *************************** 17 MEMBER OF('[23, "abc", "17", "ab", 10]'): 0 "17" MEMBER OF('[23, "abc", 17, "ab", 10]'): 0 1 row in set (0.00 sec)若要將此運算子與本身是陣列的值搭配使用,必須將其明確轉換為 JSON 陣列。您可以使用
CAST(... AS JSON)來執行此操作mysql> SELECT CAST('[4,5]' AS JSON) MEMBER OF('[[3,4],[4,5]]'); +--------------------------------------------------+ | CAST('[4,5]' AS JSON) MEMBER OF('[[3,4],[4,5]]') | +--------------------------------------------------+ | 1 | +--------------------------------------------------+ 1 row in set (0.00 sec)也可以使用
JSON_ARRAY()函數來執行必要的轉換,如下所示mysql> SELECT JSON_ARRAY(4,5) MEMBER OF('[[3,4],[4,5]]'); +--------------------------------------------+ | JSON_ARRAY(4,5) MEMBER OF('[[3,4],[4,5]]') | +--------------------------------------------+ | 1 | +--------------------------------------------+ 1 row in set (0.00 sec)任何用作要測試的值或出現在目標陣列中的 JSON 物件都必須使用
CAST(... AS JSON)或JSON_OBJECT()強制轉換為正確的類型。此外,包含 JSON 物件的目標陣列本身也必須使用JSON_ARRAY轉換。以下一系列語句說明了這一點mysql> SET @a = CAST('{"a":1}' AS JSON); Query OK, 0 rows affected (0.00 sec) mysql> SET @b = JSON_OBJECT("b", 2); Query OK, 0 rows affected (0.00 sec) mysql> SET @c = JSON_ARRAY(17, @b, "abc", @a, 23); Query OK, 0 rows affected (0.00 sec) mysql> SELECT @a MEMBER OF(@c), @b MEMBER OF(@c); +------------------+------------------+ | @a MEMBER OF(@c) | @b MEMBER OF(@c) | +------------------+------------------+ | 1 | 1 | +------------------+------------------+ 1 row in set (0.00 sec)