本節中的函數會對 JSON 值執行搜尋或比較運算,以便從中擷取資料、報告資料是否存在於其中的某個位置,或報告資料在其中的路徑。此處也會記錄 MEMBER OF()
運算子。
JSON_CONTAINS(
target
,candidate
[,path
])透過傳回 1 或 0 來表示指定的
candidate
JSON 文件是否包含在target
JSON 文件中,或者如果提供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 ERROR
json_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
:傳回提供的value
ON EMPTYvalue
。值的類型必須與回傳類型相符。ERROR ON EMPTY
:函數會拋出錯誤。
如果使用
on_error
,則會採用下列其中一個值,並在發生錯誤時產生相應的結果,如下所示NULL ON ERROR
:JSON_VALUE()
會傳回NULL
;如果沒有使用ON ERROR
子句,這是預設行為。DEFAULT
:這是傳回的值;其值必須與回傳類型相符。value
ON 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
,path
RETURNINGtype
)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)