文件首頁
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.8 JSON 實用函數

本節說明作用於 JSON 值或可剖析為 JSON 值的字串的實用函數。JSON_PRETTY() 會以易於閱讀的格式列印 JSON 值。JSON_STORAGE_SIZE()JSON_STORAGE_FREE() 分別顯示給定 JSON 值所使用的儲存空間量,以及部分更新後 JSON 欄位中剩餘的空間量。

  • JSON_PRETTY(json_val)

    提供 JSON 值的漂亮列印,類似於 PHP 和其他語言及資料庫系統中實作的列印方式。提供的值必須是 JSON 值或 JSON 值的有效字串表示。此值中存在的多餘空格和換行符號對輸出沒有影響。對於 NULL 值,該函數會傳回 NULL。如果該值不是 JSON 文件,或無法剖析為 JSON 文件,該函數會失敗並出現錯誤。

    此函數的輸出格式遵循下列規則

    • 每個陣列元素或物件成員都會出現在單獨的行上,與其父元素相比縮排一個額外層級。

    • 每個縮排層級都會新增兩個前導空格。

    • 分隔各個陣列元素或物件成員的逗號會列印在分隔兩個元素或成員的換行符號之前。

    • 物件成員的索引鍵和值之間以冒號後接一個空格 (': ') 分隔。

    • 空的物件或陣列會列印在單行上。在開頭和結尾的大括號之間不會列印空格。

    • 字串純量和索引鍵名稱中的特殊字元會使用 JSON_QUOTE() 函數所使用的相同規則逸出。

    mysql> SELECT JSON_PRETTY('123'); # scalar
    +--------------------+
    | JSON_PRETTY('123') |
    +--------------------+
    | 123                |
    +--------------------+
    
    mysql> SELECT JSON_PRETTY("[1,3,5]"); # array
    +------------------------+
    | JSON_PRETTY("[1,3,5]") |
    +------------------------+
    | [
      1,
      3,
      5
    ]      |
    +------------------------+
    
    mysql> SELECT JSON_PRETTY('{"a":"10","b":"15","x":"25"}'); # object
    +---------------------------------------------+
    | JSON_PRETTY('{"a":"10","b":"15","x":"25"}') |
    +---------------------------------------------+
    | {
      "a": "10",
      "b": "15",
      "x": "25"
    }   |
    +---------------------------------------------+
    
    mysql> SELECT JSON_PRETTY('["a",1,{"key1":
        '>    "value1"},"5",     "77" ,
        '>       {"key2":["value3","valueX",
        '> "valueY"]},"j", "2"   ]')\G  # nested arrays and objects
    *************************** 1. row ***************************
    JSON_PRETTY('["a",1,{"key1":
                 "value1"},"5",     "77" ,
                    {"key2":["value3","valuex",
              "valuey"]},"j", "2"   ]'): [
      "a",
      1,
      {
        "key1": "value1"
      },
      "5",
      "77",
      {
        "key2": [
          "value3",
          "valuex",
          "valuey"
        ]
      },
      "j",
      "2"
    ]
  • JSON_STORAGE_FREE(json_val)

    對於 JSON 欄位值,此函數會顯示在使用 JSON_SET()JSON_REPLACE()JSON_REMOVE()就地更新後,其二進位表示法中釋放了多少儲存空間。引數也可以是有效的 JSON 文件或可剖析為 JSON 文件的字串(以常值或使用者變數的值的形式),在這種情況下,函數會傳回 0。如果引數是 JSON 欄位值,且已如先前所述進行更新,使其二進位表示法佔用的空間小於更新前,則它會傳回正的非零值。對於已更新的 JSON 欄位,使其二進位表示法與更新前相同或更大,或者如果更新無法利用部分更新,則它會傳回 0;如果引數為 NULL,則它會傳回 NULL

    如果 json_val 不是 NULL,也不是有效的 JSON 文件,也無法成功剖析為 JSON 文件,就會產生錯誤。

    在此範例中,我們建立一個包含 JSON 欄位的表格,然後插入包含 JSON 物件的資料列

    mysql> CREATE TABLE jtable (jcol JSON);
    Query OK, 0 rows affected (0.38 sec)
    
    mysql> INSERT INTO jtable VALUES
        ->     ('{"a": 10, "b": "wxyz", "c": "[true, false]"}');
    Query OK, 1 row affected (0.04 sec)
    
    mysql> SELECT * FROM jtable;
    +----------------------------------------------+
    | jcol                                         |
    +----------------------------------------------+
    | {"a": 10, "b": "wxyz", "c": "[true, false]"} |
    +----------------------------------------------+
    1 row in set (0.00 sec)

    現在我們使用 JSON_SET() 更新欄位值,以便可以執行部分更新;在此情況下,我們將索引鍵 c 所指向的值(陣列 [true, false])取代為佔用較少空間的值(整數 1

    mysql> UPDATE jtable
        ->     SET jcol = JSON_SET(jcol, "$.a", 10, "$.b", "wxyz", "$.c", 1);
    Query OK, 1 row affected (0.03 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    
    mysql> SELECT * FROM jtable;
    +--------------------------------+
    | jcol                           |
    +--------------------------------+
    | {"a": 10, "b": "wxyz", "c": 1} |
    +--------------------------------+
    1 row in set (0.00 sec)
    
    mysql> SELECT JSON_STORAGE_FREE(jcol) FROM jtable;
    +-------------------------+
    | JSON_STORAGE_FREE(jcol) |
    +-------------------------+
    |                      14 |
    +-------------------------+
    1 row in set (0.00 sec)

    連續部分更新對此可用空間的影響是累積的,如以下範例所示,使用 JSON_SET() 減少索引鍵為 b 的值所佔用的空間(且不做任何其他變更)

    mysql> UPDATE jtable
        ->     SET jcol = JSON_SET(jcol, "$.a", 10, "$.b", "wx", "$.c", 1);
    Query OK, 1 row affected (0.03 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    
    mysql> SELECT JSON_STORAGE_FREE(jcol) FROM jtable;
    +-------------------------+
    | JSON_STORAGE_FREE(jcol) |
    +-------------------------+
    |                      16 |
    +-------------------------+
    1 row in set (0.00 sec)

    在不使用 JSON_SET()JSON_REPLACE()JSON_REMOVE() 的情況下更新欄位表示最佳化工具無法就地執行更新;在此情況下,JSON_STORAGE_FREE() 會傳回 0,如下所示

    mysql> UPDATE jtable SET jcol = '{"a": 10, "b": 1}';
    Query OK, 1 row affected (0.05 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    
    mysql> SELECT JSON_STORAGE_FREE(jcol) FROM jtable;
    +-------------------------+
    | JSON_STORAGE_FREE(jcol) |
    +-------------------------+
    |                       0 |
    +-------------------------+
    1 row in set (0.00 sec)

    JSON 文件的一部分更新只能在欄位值上執行。對於儲存 JSON 值的使用者變數,即使使用 JSON_SET() 執行更新,該值也總是會被完全取代

    mysql> SET @j = '{"a": 10, "b": "wxyz", "c": "[true, false]"}';
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SET @j = JSON_SET(@j, '$.a', 10, '$.b', 'wxyz', '$.c', '1');
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SELECT @j, JSON_STORAGE_FREE(@j) AS Free;
    +----------------------------------+------+
    | @j                               | Free |
    +----------------------------------+------+
    | {"a": 10, "b": "wxyz", "c": "1"} |    0 |
    +----------------------------------+------+
    1 row in set (0.00 sec)

    對於 JSON 常值,此函數始終傳回 0

    mysql> SELECT JSON_STORAGE_FREE('{"a": 10, "b": "wxyz", "c": "1"}') AS Free;
    +------+
    | Free |
    +------+
    |    0 |
    +------+
    1 row in set (0.00 sec)
  • JSON_STORAGE_SIZE(json_val)

    此函數會傳回用於儲存 JSON 文件的二進位表示法的位元組數。當引數為 JSON 欄位時,這是用於儲存 JSON 文件的方式,該文件會先插入欄位中,然後才會對其執行任何部分更新。json_val 必須是有效的 JSON 文件,或可剖析為 JSON 文件的字串。如果它是字串,則此函數會傳回將字串剖析為 JSON 並轉換為二進位所建立的 JSON 二進位表示法中的儲存空間量。如果引數為 NULL,則它會傳回 NULL

    json_val 不是 NULL,且不是(或無法成功剖析為)JSON 文件時,就會產生錯誤。

    為了說明此函數在使用 JSON 欄位作為引數時的行為,我們建立一個名為 jtable 的資料表,其中包含一個 JSON 欄位 jcol,將一個 JSON 值插入該資料表,然後使用 JSON_STORAGE_SIZE() 取得此欄位使用的儲存空間,如下所示

    mysql> CREATE TABLE jtable (jcol JSON);
    Query OK, 0 rows affected (0.42 sec)
    
    mysql> INSERT INTO jtable VALUES
        ->     ('{"a": 1000, "b": "wxyz", "c": "[1, 3, 5, 7]"}');
    Query OK, 1 row affected (0.04 sec)
    
    mysql> SELECT
        ->     jcol,
        ->     JSON_STORAGE_SIZE(jcol) AS Size,
        ->     JSON_STORAGE_FREE(jcol) AS Free
        -> FROM jtable;
    +-----------------------------------------------+------+------+
    | jcol                                          | Size | Free |
    +-----------------------------------------------+------+------+
    | {"a": 1000, "b": "wxyz", "c": "[1, 3, 5, 7]"} |   47 |    0 |
    +-----------------------------------------------+------+------+
    1 row in set (0.00 sec)

    根據 JSON_STORAGE_SIZE() 的輸出,插入到該欄位的 JSON 文件佔用了 47 個位元組。我們還使用 JSON_STORAGE_FREE() 檢查了先前對欄位進行部分更新所釋放的空間量;由於尚未執行任何更新,因此如預期為 0。

    接下來,我們對資料表執行 UPDATE,該更新應該會導致儲存在 jcol 中的文件進行部分更新,然後測試結果,如下所示

    mysql> UPDATE jtable SET jcol = 
        ->     JSON_SET(jcol, "$.b", "a");
    Query OK, 1 row affected (0.04 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    
    mysql> SELECT
        ->     jcol,
        ->     JSON_STORAGE_SIZE(jcol) AS Size,
        ->     JSON_STORAGE_FREE(jcol) AS Free
        -> FROM jtable;
    +--------------------------------------------+------+------+
    | jcol                                       | Size | Free |
    +--------------------------------------------+------+------+
    | {"a": 1000, "b": "a", "c": "[1, 3, 5, 7]"} |   47 |    3 |
    +--------------------------------------------+------+------+
    1 row in set (0.00 sec)

    先前查詢中 JSON_STORAGE_FREE() 返回的值表示已對 JSON 文件執行部分更新,並且釋放了 3 個位元組的儲存空間。 JSON_STORAGE_SIZE() 返回的結果不會因部分更新而改變。

    使用 JSON_SET()JSON_REPLACE()JSON_REMOVE() 進行更新時,支援部分更新。將值直接指派給 JSON 欄位無法進行部分更新;在進行此類更新後,JSON_STORAGE_SIZE() 始終顯示新設定值所使用的儲存空間

    mysql> UPDATE jtable
    mysql>     SET jcol = '{"a": 4.55, "b": "wxyz", "c": "[true, false]"}';
    Query OK, 1 row affected (0.04 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    
    mysql> SELECT
        ->     jcol,
        ->     JSON_STORAGE_SIZE(jcol) AS Size,
        ->     JSON_STORAGE_FREE(jcol) AS Free
        -> FROM jtable;
    +------------------------------------------------+------+------+
    | jcol                                           | Size | Free |
    +------------------------------------------------+------+------+
    | {"a": 4.55, "b": "wxyz", "c": "[true, false]"} |   56 |    0 |
    +------------------------------------------------+------+------+
    1 row in set (0.00 sec)

    JSON 使用者變數無法進行部分更新。這表示此函數始終顯示目前用於儲存使用者變數中 JSON 文件的空間

    mysql> SET @j = '[100, "sakila", [1, 3, 5], 425.05]';
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SELECT @j, JSON_STORAGE_SIZE(@j) AS Size;
    +------------------------------------+------+
    | @j                                 | Size |
    +------------------------------------+------+
    | [100, "sakila", [1, 3, 5], 425.05] |   45 |
    +------------------------------------+------+
    1 row in set (0.00 sec)
    
    mysql> SET @j = JSON_SET(@j, '$[1]', "json");
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SELECT @j, JSON_STORAGE_SIZE(@j) AS Size;
    +----------------------------------+------+
    | @j                               | Size |
    +----------------------------------+------+
    | [100, "json", [1, 3, 5], 425.05] |   43 |
    +----------------------------------+------+
    1 row in set (0.00 sec)
    
    mysql> SET @j = JSON_SET(@j, '$[2][0]', JSON_ARRAY(10, 20, 30));
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SELECT @j, JSON_STORAGE_SIZE(@j) AS Size;
    +---------------------------------------------+------+
    | @j                                          | Size |
    +---------------------------------------------+------+
    | [100, "json", [[10, 20, 30], 3, 5], 425.05] |   56 |
    +---------------------------------------------+------+
    1 row in set (0.00 sec)

    對於 JSON 常值,此函數始終返回目前使用的儲存空間

    mysql> SELECT
        ->     JSON_STORAGE_SIZE('[100, "sakila", [1, 3, 5], 425.05]') AS A,
        ->     JSON_STORAGE_SIZE('{"a": 1000, "b": "a", "c": "[1, 3, 5, 7]"}') AS B,
        ->     JSON_STORAGE_SIZE('{"a": 1000, "b": "wxyz", "c": "[1, 3, 5, 7]"}') AS C,
        ->     JSON_STORAGE_SIZE('[100, "json", [[10, 20, 30], 3, 5], 425.05]') AS D;
    +----+----+----+----+
    | A  | B  | C  | D  |
    +----+----+----+----+
    | 45 | 44 | 47 | 56 |
    +----+----+----+----+
    1 row in set (0.00 sec)