文件首頁
MySQL 9.0 參考手冊
相關文件 下載本手冊
PDF (美國 Letter) - 40.0Mb
PDF (A4) - 40.1Mb
Man Pages (TGZ) - 258.2Kb
Man Pages (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 9.0 參考手冊  /  ...  /  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)