文件首頁
MySQL 8.4 參考手冊
相關文件 下載本手冊
PDF (美國信紙) - 39.9Mb
PDF (A4) - 40.0Mb
Man Pages (TGZ) - 258.5Kb
Man Pages (Zip) - 365.5Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 參考手冊  /  ...  /  搜尋 JSON 值的函式

14.17.3 搜尋 JSON 值的函式

本節中的函式會對 JSON 值執行搜尋或比較操作,以從中提取資料、報告資料是否存在於其中的某個位置,或報告其中資料的路徑。MEMBER OF() 運算子也會在此處記錄。

  • JSON_CONTAINS(目標, 候選[, 路徑])

    透過傳回 1 或 0 來指示指定的 候選 JSON 文件是否包含在 目標 JSON 文件中,或—如果提供 路徑 引數—是否在目標中的特定路徑找到候選。如果任何引數為 NULL,或路徑引數未識別目標文件的區段,則傳回 NULL。如果 目標候選 不是有效的 JSON 文件,或 路徑 引數不是有效的路徑表達式或包含 *** 萬用字元,則會發生錯誤。

    若僅檢查路徑上是否存在任何資料,請改用 JSON_CONTAINS_PATH()

    以下規則定義包含關係

    • 當且僅當候選純量與目標純量可比較且相等時,候選純量才會包含在目標純量中。當兩個純量值具有相同的 JSON_TYPE() 類型時,它們是可比較的,但類型為 INTEGERDECIMAL 的值彼此之間也是可比較的。

    • 當且僅當候選陣列中的每個元素都包含在目標陣列的某些元素中時,候選陣列才會包含在目標陣列中。

    • 當且僅當候選非陣列包含在目標陣列的某些元素中時,候選非陣列才會包含在目標陣列中。

    • 當且僅當候選物件中的每個索引鍵在目標中都有一個相同名稱的索引鍵,且與候選索引鍵相關聯的值包含在與目標索引鍵相關聯的值中時,候選物件才會包含在目標物件中。

    否則,候選值不會包含在目標文件中。

    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 路徑。

  • column->path

    當使用兩個引數時,-> 運算子充當 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)
  • column->>path

    這是一個經過改良的、解除引號的擷取運算子。 -> 運算子只是簡單地擷取值,而 ->> 運算子還會解除擷取結果的引號。換句話說,給定一個 JSON 資料行值 column 和一個路徑運算式 path(字串常值),以下三個運算式會傳回相同的值

    ->> 運算子可以在允許 JSON_UNQUOTE(JSON_EXTRACT()) 的任何地方使用。這包括(但不限於)SELECT 清單、WHEREHAVING 子句,以及 ORDER BYGROUP 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_KEYS(json_doc[, path])

    以 JSON 陣列的形式傳回 JSON 物件最上層值的鍵,或者,如果提供 path 引數,則傳回選定路徑的最上層鍵。如果任何引數為 NULLjson_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,如果它們沒有共用任何陣列元素,則傳回 false

    mysql> 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_docsearch_strpath 引數為 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_VALUE(json_doc, path)

    從指定文件中給定路徑的 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 EMPTY:會傳回提供的 value。值的類型必須與傳回類型相符。

    • ERROR ON EMPTY:函式會擲回錯誤。

    如果使用 on_error,它會採用下列其中一個值,並在發生錯誤時產生對應的結果,如下所示

    • NULL ON ERRORJSON_VALUE() 會傳回 NULL;如果未使用任何 ON ERROR 子句,則此為預設行為。

    • DEFAULT value ON ERROR:這是傳回的值;其值必須與傳回類型相符。

    • ERROR ON ERROR:會擲回錯誤。

    如果使用 ON EMPTY,必須在任何 ON ERROR 子句之前。以錯誤的順序指定它們會導致語法錯誤。

    錯誤處理。 一般而言,JSON_VALUE() 會依以下方式處理錯誤

    • 所有 JSON 輸入(文件和路徑)都會檢查其有效性。如果任何輸入無效,則會擲回 SQL 錯誤,而不會觸發 ON ERROR 子句。

    • 每當發生下列任何事件時,就會觸發 ON ERROR

      • 嘗試擷取物件或陣列,例如因解析為 JSON 文件中多個位置的路徑所導致的物件或陣列

      • 轉換錯誤,例如嘗試將 'asdf' 轉換為 UNSIGNED

      • 值截斷

    • 即使指定了 NULL ON ERRORDEFAULT ... 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 RETURNING type) 等同於下列陳述式

    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 MEMBER OF(json_array)

    如果 valuejson_array 的元素,則傳回 true (1),否則傳回 false (0)。value 必須為純量或 JSON 文件;如果為純量,運算子會嘗試將其視為 JSON 陣列的元素。如果 valuejson_arrayNULL,則函式會傳回 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)