本節中的函式會對 JSON 值執行搜尋或比較操作,以從中提取資料、報告資料是否存在於其中的某個位置,或報告其中資料的路徑。MEMBER OF()
運算子也會在此處記錄。
透過傳回 1 或 0 來指示指定的
候選
JSON 文件是否包含在目標
JSON 文件中,或—如果提供路徑
引數—是否在目標中的特定路徑找到候選。如果任何引數為NULL
,或路徑引數未識別目標文件的區段,則傳回NULL
。如果目標
或候選
不是有效的 JSON 文件,或路徑
引數不是有效的路徑表達式或包含*
或**
萬用字元,則會發生錯誤。若僅檢查路徑上是否存在任何資料,請改用
JSON_CONTAINS_PATH()
。以下規則定義包含關係
當且僅當候選純量與目標純量可比較且相等時,候選純量才會包含在目標純量中。當兩個純量值具有相同的
JSON_TYPE()
類型時,它們是可比較的,但類型為INTEGER
和DECIMAL
的值彼此之間也是可比較的。當且僅當候選陣列中的每個元素都包含在目標陣列的某些元素中時,候選陣列才會包含在目標陣列中。
當且僅當候選非陣列包含在目標陣列的某些元素中時,候選非陣列才會包含在目標陣列中。
當且僅當候選物件中的每個索引鍵在目標中都有一個相同名稱的索引鍵,且與候選索引鍵相關聯的值包含在與目標索引鍵相關聯的值中時,候選物件才會包含在目標物件中。
否則,候選值不會包含在目標文件中。
在
InnoDB
表格上使用JSON_CONTAINS()
的查詢可以使用多值索引進行最佳化;請參閱多值索引以取得更多資訊。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
,路徑
[,路徑
] ...)傳回 0 或 1 以指示 JSON 文件是否在給定路徑或路徑上包含資料。如果任何引數為
NULL
,則傳回NULL
。如果json_doc
引數不是有效的 JSON 文件,任何路徑
引數不是有效的路徑表達式,或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
,路徑
[,路徑
] ...)從 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)
請參閱 為 JSON 資料行索引提供索引產生的資料行,以了解用於建立和填入剛才所示範例集中的
jemp
表格的 SQL 陳述式。此運算子也可以與 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
,則傳回NULL
;文件中不存在任何path
;或找不到search_str
。如果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 空值常值時,函式會傳回 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
。在
WHERE
子句中,對InnoDB
資料表的 JSON 資料行使用MEMBER OF()
的查詢,可以使用多值索引進行最佳化。如需詳細資訊和範例,請參閱 多值索引。簡單的純量會被視為陣列值,如下所示
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)
必須使用
CAST(... AS JSON)
或JSON_OBJECT()
,將用作要測試之值的任何 JSON 物件,或出現在目標陣列中的 JSON 物件,強制轉換為正確的類型。此外,包含 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)