支援的版本:目前 (17) / 16 / 15 / 14 / 13
開發版本:devel
不支援的版本:12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2

9.16. JSON 函數與運算子 #

本節描述

  • 處理與建立 JSON 資料的函數與運算子

  • SQL/JSON 路徑語言

  • SQL/JSON 查詢函數

為了在 SQL 環境中提供對 JSON 資料類型的原生支援,PostgreSQL 實作了SQL/JSON 資料模型。此模型包含項目序列。每個項目可以保存 SQL 純量值,以及額外的 SQL/JSON null 值,以及使用 JSON 陣列和物件的複合資料結構。該模型是 JSON 規範 RFC 7159 中隱含資料模型的形式化。

SQL/JSON 允許您處理 JSON 資料以及正規的 SQL 資料,並提供交易支援,包括

  • 將 JSON 資料上傳到資料庫,並以字元或二進位字串形式儲存在正規的 SQL 欄位中。

  • 從關聯式資料產生 JSON 物件和陣列。

  • 使用 SQL/JSON 查詢函數和 SQL/JSON 路徑語言表達式查詢 JSON 資料。

若要瞭解更多關於 SQL/JSON 標準的資訊,請參閱 [sqltr-19075-6]。關於 PostgreSQL 中支援的 JSON 類型的詳細資訊,請參閱 第 8.14 節

9.16.1. 處理與建立 JSON 資料 #

表 9.45 顯示了可用於 JSON 資料類型的運算子(請參閱 第 8.14 節)。此外,表 9.1 中顯示的常用比較運算子可用於 jsonb,但不適用於 json。比較運算子遵循 第 8.14.4 節中概述的 B 樹運算的排序規則。另請參閱 第 9.21 節,瞭解將記錄值彙總為 JSON 的彙總函數 json_agg,將數值對彙總為 JSON 物件的彙總函數 json_object_agg,以及它們的 jsonb 對應物 jsonb_aggjsonb_object_agg

表 9.45. jsonjsonb 運算子

運算子

描述

範例

json -> integerjson

jsonb -> integerjsonb

提取 JSON 陣列的第 n 個元素(陣列元素的索引從零開始,但負整數從末尾開始計數)。

'[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json -> 2{"c":"baz"}

'[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json -> -3{"a":"foo"}

json -> textjson

jsonb -> textjsonb

提取具有給定鍵值的 JSON 物件欄位。

'{"a": {"b":"foo"}}'::json -> 'a'{"b":"foo"}

json ->> integertext

jsonb ->> integertext

提取 JSON 陣列的第 n 個元素,作為 text

'[1,2,3]'::json ->> 23

json ->> texttext

jsonb ->> texttext

提取具有給定鍵值的 JSON 物件欄位,作為 text

'{"a":1,"b":2}'::json ->> 'b'2

json #> text[]json

jsonb #> text[]jsonb

提取指定路徑的 JSON 子物件,其中路徑元素可以是欄位鍵值或陣列索引。

'{"a": {"b": ["foo","bar"]}}'::json #> '{a,b,1}'"bar"

json #>> text[]text

jsonb #>> text[]text

提取指定路徑的 JSON 子物件,作為 text

'{"a": {"b": ["foo","bar"]}}'::json #>> '{a,b,1}'bar


注意

如果 JSON 輸入沒有正確的結構來匹配請求(例如,如果不存在此類鍵值或陣列元素),則欄位/元素/路徑提取運算子會傳回 NULL,而不是失敗。

某些額外的運算子僅適用於 jsonb,如 表 9.46 所示。第 8.14.4 節 描述了如何使用這些運算子來有效地搜尋已編製索引的 jsonb 資料。

表 9.46. 額外的 jsonb 運算子

運算子

描述

範例

jsonb @> jsonbboolean

第一個 JSON 值是否包含第二個值?(有關包含的詳細資訊,請參閱 第 8.14.3 節。)

'{"a":1, "b":2}'::jsonb @> '{"b":2}'::jsonbt

jsonb <@ jsonbboolean

第一個 JSON 值是否包含於第二個 JSON 值中?

'{"b":2}'::jsonb <@ '{"a":1, "b":2}'::jsonbt

jsonb ? textboolean

該文字字串是否存在於 JSON 值中的最上層鍵或陣列元素?

'{"a":1, "b":2}'::jsonb ? 'b't

'["a", "b", "c"]'::jsonb ? 'b't

jsonb ?| text[]boolean

文字陣列中的任何字串是否存在於最上層鍵或陣列元素中?

'{"a":1, "b":2, "c":3}'::jsonb ?| array['b', 'd']t

jsonb ?& text[]boolean

文字陣列中的所有字串是否存在於最上層鍵或陣列元素中?

'["a", "b", "c"]'::jsonb ?& array['a', 'b']t

jsonb || jsonbjsonb

串聯兩個 jsonb 值。串聯兩個陣列會產生一個包含每個輸入的所有元素的陣列。串聯兩個物件會產生一個包含它們鍵的聯集的物件,當存在重複鍵時,採用第二個物件的值。所有其他情況都將透過將非陣列輸入轉換為單一元素陣列來處理,然後像處理兩個陣列一樣繼續。不會遞迴操作:僅合併最上層陣列或物件結構。

'["a", "b"]'::jsonb || '["a", "d"]'::jsonb["a", "b", "a", "d"]

'{"a": "b"}'::jsonb || '{"c": "d"}'::jsonb{"a": "b", "c": "d"}

'[1, 2]'::jsonb || '3'::jsonb[1, 2, 3]

'{"a": "b"}'::jsonb || '42'::jsonb[{"a": "b"}, 42]

若要將陣列作為單一條目附加到另一個陣列,請將其包裝在額外的陣列層中,例如

'[1, 2]'::jsonb || jsonb_build_array('[3, 4]'::jsonb)[1, 2, [3, 4]]

jsonb - textjsonb

從 JSON 物件中刪除鍵(及其值),或從 JSON 陣列中刪除相符的字串值。

'{"a": "b", "c": "d"}'::jsonb - 'a'{"c": "d"}

'["a", "b", "c", "b"]'::jsonb - 'b'["a", "c"]

jsonb - text[]jsonb

從左運算元刪除所有相符的鍵或陣列元素。

'{"a": "b", "c": "d"}'::jsonb - '{a,c}'::text[]{}

jsonb - integerjsonb

刪除具有指定索引的陣列元素(負整數從末尾算起)。如果 JSON 值不是陣列,則會擲回錯誤。

'["a", "b"]'::jsonb - 1["a"]

jsonb #- text[]jsonb

刪除指定路徑上的欄位或陣列元素,其中路徑元素可以是欄位鍵或陣列索引。

'["a", {"b":1}]'::jsonb #- '{1,b}'["a", {}]

jsonb @? jsonpathboolean

JSON 路徑是否為指定的 JSON 值傳回任何項目? (這僅在 SQL 標準 JSON 路徑表示式中才有用,而不是謂詞檢查表示式,因為這些表示式始終傳回值。)

'{"a":[1,2,3,4,5]}'::jsonb @? '$.a[*] ? (@ > 2)'t

jsonb @@ jsonpathboolean

傳回指定 JSON 值的 JSON 路徑謂詞檢查的結果。(這僅在謂詞檢查表示式中才有用,而不是 SQL 標準 JSON 路徑表示式,因為如果路徑結果不是單一布林值,它將傳回 NULL。)

'{"a":[1,2,3,4,5]}'::jsonb @@ '$.a[*] > 2't


注意

jsonpath 運算子 @?@@ 會抑制以下錯誤:遺失物件欄位或陣列元素、意外的 JSON 項目類型、日期時間和數值錯誤。 下面描述的 jsonpath 相關函數也可以被告知抑制這些類型的錯誤。 當搜尋具有不同結構的 JSON 文件集合時,此行為可能會有所幫助。

表 9.47 顯示了可用於建構 jsonjsonb 值的函數。 此表中的某些函數具有 RETURNING 子句,該子句指定傳回的資料類型。 它必須是 jsonjsonbbytea、字元串類型(textcharvarchar)之一,或者是可以轉換為 json 的類型。 預設情況下,傳回 json 類型。

表 9.47. JSON 建立函數

函數

描述

範例

to_json ( anyelement ) → json

to_jsonb ( anyelement ) → jsonb

將任何 SQL 值轉換為 jsonjsonb。 陣列和複合類型會以遞迴方式轉換為陣列和物件(多維陣列在 JSON 中變成陣列的陣列)。 否則,如果存在從 SQL 資料類型到 json 的轉換,則將使用轉換函數執行轉換;[a] 否則,將產生純量 JSON 值。 對於任何不是數字、布林值或空值的純量,將使用文字表示形式,並進行必要的逸出以使其成為有效的 JSON 字串值。

to_json('Fred said "Hi."'::text)"Fred said \"Hi.\""

to_jsonb(row(42, 'Fred said "Hi."'::text)){"f1": 42, "f2": "Fred said \"Hi.\""}

array_to_json ( anyarray [, boolean ] ) → json

將 SQL 陣列轉換為 JSON 陣列。其行為與 to_json 相同,差別在於如果選擇性的布林參數為 true,則會在最上層陣列元素之間加入換行符號。

array_to_json('{{1,5},{99,100}}'::int[])[[1,5],[99,100]]

json_array ( [ { value_expression [ FORMAT JSON ] } [, ...] ] [ { NULL | ABSENT } ON NULL ] [ RETURNING data_type [ FORMAT JSON [ ENCODING UTF8 ] ] ])

json_array ( [ query_expression ] [ RETURNING data_type [ FORMAT JSON [ ENCODING UTF8 ] ] ])

從一系列的 value_expression 參數或 query_expression 的結果建構一個 JSON 陣列,query_expression 必須是一個 SELECT 查詢,且回傳單一欄位。如果指定了 ABSENT ON NULL,則會忽略 NULL 值。如果使用了 query_expression,則總是如此。

json_array(1,true,json '{"a":null}')[1, true, {"a":null}]

json_array(SELECT * FROM (VALUES(1),(2)) t)[1, 2]

row_to_json ( record [, boolean ] ) → json

將 SQL 複合值轉換為 JSON 物件。其行為與 to_json 相同,差別在於如果選擇性的布林參數為 true,則會在最上層元素之間加入換行符號。

row_to_json(row(1,'foo')){"f1":1,"f2":"foo"}

json_build_array ( VARIADIC "any" ) → json

jsonb_build_array ( VARIADIC "any" ) → jsonb

從可變參數清單建構一個可能具有異質型別的 JSON 陣列。每個參數都會依照 to_jsonto_jsonb 進行轉換。

json_build_array(1, 2, 'foo', 4, 5)[1, 2, "foo", 4, 5]

json_build_object ( VARIADIC "any" ) → json

jsonb_build_object ( VARIADIC "any" ) → jsonb

從可變參數清單建構一個 JSON 物件。 依照慣例,參數清單由交替的鍵和值組成。 鍵參數會強制轉換為文字;值參數會依照 to_jsonto_jsonb 進行轉換。

json_build_object('foo', 1, 2, row(3,'bar')){"foo" : 1, "2" : {"f1":3,"f2":"bar"}}

json_object ( [ { key_expression { VALUE | ':' } value_expression [ FORMAT JSON [ ENCODING UTF8 ] ] }[, ...] ] [ { NULL | ABSENT } ON NULL ] [ { WITH | WITHOUT } UNIQUE [ KEYS ] ] [ RETURNING data_type [ FORMAT JSON [ ENCODING UTF8 ] ] ])

建構一個包含所有給定的鍵/值配對的 JSON 物件,如果沒有給定任何配對,則建構一個空物件。key_expression 是一個定義JSON鍵的純量表達式,它會轉換為 text 型別。 它不能是 NULL,也不能屬於具有轉換為 json 型別的型別。 如果指定了 WITH UNIQUE KEYS,則不能有任何重複的 key_expression。 如果 value_expression 評估為 NULL,且指定了 ABSENT ON NULL,則會從輸出中省略該配對;如果指定了 NULL ON NULL 或省略了該子句,則該鍵會包含在值 NULL 中。

json_object('code' VALUE 'P123', 'title': 'Jaws'){"code" : "P123", "title" : "Jaws"}

json_object ( text[] ) → json

jsonb_object ( text[] ) → jsonb

從文字陣列建構一個 JSON 物件。 陣列必須只有一個維度且成員數為偶數,在這種情況下,它們會被視為交替的鍵/值配對,或者具有兩個維度,且每個內部陣列恰好有兩個元素,這些元素會被視為鍵/值配對。 所有值都會轉換為 JSON 字串。

json_object('{a, 1, b, "def", c, 3.5}'){"a" : "1", "b" : "def", "c" : "3.5"}

json_object('{{a, 1}, {b, "def"}, {c, 3.5}}'){"a" : "1", "b" : "def", "c" : "3.5"}

json_object ( keys text[], values text[] ) → json

jsonb_object ( keys text[], values text[] ) → jsonb

此形式的 json_object 從單獨的文字陣列中成對取得鍵和值。 否則它與單參數形式相同。

json_object('{a,b}', '{1,2}'){"a": "1", "b": "2"}

json ( expression [ FORMAT JSON [ ENCODING UTF8 ]] [ { WITH | WITHOUT } UNIQUE [ KEYS ]] ) → json

將指定的表示式(以 UTF8 編碼的 textbytea 字串形式)轉換為 JSON 值。如果 expression 為 NULL,則會回傳SQLnull 值。如果指定 WITH UNIQUE,則 expression 不得包含任何重複的物件鍵。

json('{"a":123, "b":[true,"foo"], "a":"bar"}'){"a":123, "b":[true,"foo"], "a":"bar"}

json_scalar ( expression )

將指定的 SQL 純量值轉換為 JSON 純量值。如果輸入為 NULL,則會回傳SQLnull。如果輸入為數字或布林值,則會回傳對應的 JSON 數字或布林值。對於任何其他值,則會回傳 JSON 字串。

json_scalar(123.45)123.45

json_scalar(CURRENT_TIMESTAMP)"2022-05-10T10:51:04.62128-04:00"

json_serialize ( expression [ FORMAT JSON [ ENCODING UTF8 ] ] [ RETURNING data_type [ FORMAT JSON [ ENCODING UTF8 ] ] ] )

將 SQL/JSON 表示式轉換為字元或二進位字串。expression 可以是任何 JSON 類型、任何字元串類型或 UTF8 編碼的 byteaRETURNING 中使用的回傳類型可以是任何字元串類型或 bytea。預設值為 text

json_serialize('{ "a" : 1 } ' RETURNING bytea)\x7b20226122203a2031207d20

[a] 例如,hstore 擴充功能具有從 hstorejson 的轉換,因此透過 JSON 建立函式轉換的 hstore 值將會表示為 JSON 物件,而不是原始字串值。


表 9.48 詳細介紹了用於測試 JSON 的 SQL/JSON 功能。

表 9.48. SQL/JSON 測試函式

函式簽章

描述

範例

expression IS [ NOT ] JSON [ { VALUE | SCALAR | ARRAY | OBJECT } ] [ { WITH | WITHOUT } UNIQUE [ KEYS ] ]

此述詞測試 expression 是否可以解析為 JSON,可能是指定類型。如果指定 SCALARARRAYOBJECT,則測試 JSON 是否為該特定類型。如果指定 WITH UNIQUE KEYS,則也會測試 expression 中的任何物件,以查看其是否具有重複的鍵。

SELECT js,
  js IS JSON "json?",
  js IS JSON SCALAR "scalar?",
  js IS JSON OBJECT "object?",
  js IS JSON ARRAY "array?"
FROM (VALUES
      ('123'), ('"abc"'), ('{"a": "b"}'), ('[1,2]'),('abc')) foo(js);
     js     | json? | scalar? | object? | array?
------------+-------+---------+---------+--------
 123        | t     | t       | f       | f
 "abc"      | t     | t       | f       | f
 {"a": "b"} | t     | f       | t       | f
 [1,2]      | t     | f       | f       | t
 abc        | f     | f       | f       | f
SELECT js,
  js IS JSON OBJECT "object?",
  js IS JSON ARRAY "array?",
  js IS JSON ARRAY WITH UNIQUE KEYS "array w. UK?",
  js IS JSON ARRAY WITHOUT UNIQUE KEYS "array w/o UK?"
FROM (VALUES ('[{"a":"1"},
 {"b":"2","b":"3"}]')) foo(js);
-[ RECORD 1 ]-+--------------------
js            | [{"a":"1"},        +
              |  {"b":"2","b":"3"}]
object?       | f
array?        | t
array w. UK?  | f
array w/o UK? | t

表 9.49 顯示了可用於處理 jsonjsonb 值的函式。

表 9.49. JSON 處理函式

函數

描述

範例

json_array_elements ( json ) → setof json

jsonb_array_elements ( jsonb ) → setof jsonb

將最上層的 JSON 陣列展開為一組 JSON 值。

select * from json_array_elements('[1,true, [2,false]]')

   value
-----------
 1
 true
 [2,false]

json_array_elements_text ( json ) → setof text

jsonb_array_elements_text ( jsonb ) → setof text

將最上層的 JSON 陣列展開為一組 text 值。

select * from json_array_elements_text('["foo", "bar"]')

   value
-----------
 foo
 bar

json_array_length ( json ) → integer

jsonb_array_length ( jsonb ) → integer

回傳最上層 JSON 陣列中的元素數量。

json_array_length('[1,2,3,{"f1":1,"f2":[5,6]},4]')5

jsonb_array_length('[]')0

json_each ( json ) → setof record ( key text, value json )

jsonb_each ( jsonb ) → setof record ( key text, value jsonb )

將最上層的 JSON 物件展開為一組鍵/值配對。

select * from json_each('{"a":"foo", "b":"bar"}')

 key | value
-----+-------
 a   | "foo"
 b   | "bar"

json_each_text ( json ) → setof record ( key text, value text )

jsonb_each_text ( jsonb ) → setof record ( key text, value text )

將最上層的 JSON 物件展開為一組鍵/值配對。回傳的 value 值將為 text 類型。

select * from json_each_text('{"a":"foo", "b":"bar"}')

 key | value
-----+-------
 a   | foo
 b   | bar

json_extract_path ( from_json json, VARIADIC path_elems text[] ) → json

jsonb_extract_path ( from_json jsonb, VARIADIC path_elems text[] ) → jsonb

提取指定路徑的 JSON 子物件。(在功能上等同於 #> 運算符,但在某些情況下,將路徑寫成可變參數列表可能更方便。)

json_extract_path('{"f2":{"f3":1},"f4":{"f5":99,"f6":"foo"}}', 'f4', 'f6')"foo"

json_extract_path_text ( from_json json, VARIADIC path_elems text[] ) → text

jsonb_extract_path_text ( from_json jsonb, VARIADIC path_elems text[] ) → text

提取指定路徑的 JSON 子物件作為 text。(在功能上等同於 #>> 運算符。)

json_extract_path_text('{"f2":{"f3":1},"f4":{"f5":99,"f6":"foo"}}', 'f4', 'f6')foo

json_object_keys ( json ) → setof text

jsonb_object_keys ( jsonb ) → setof text

傳回最上層 JSON 物件中的鍵的集合。

select * from json_object_keys('{"f1":"abc","f2":{"f3":"a", "f4":"b"}}')

 json_object_keys
------------------
 f1
 f2

json_populate_record ( base anyelement, from_json json ) → anyelement

jsonb_populate_record ( base anyelement, from_json jsonb ) → anyelement

將最上層 JSON 物件展開為具有 base 引數的複合類型的列。掃描 JSON 物件以尋找名稱與輸出列的欄位名稱相符的欄位,並將其值插入到輸出的這些欄位中。(不對應於任何輸出欄位名稱的欄位將被忽略。)在一般使用中,base 的值只是 NULL,這表示任何與物件欄位不符的輸出欄位將會填入 null 值。但是,如果 base 不是 NULL,則它包含的值將用於不符的欄位。

若要將 JSON 值轉換為輸出欄位的 SQL 類型,請依序套用下列規則

  • 在所有情況下,JSON null 值都會轉換為 SQL null。

  • 如果輸出欄位的類型為 jsonjsonb,則只會完全複製 JSON 值。

  • 如果輸出欄位是複合(列)類型,且 JSON 值是 JSON 物件,則物件的欄位會透過遞迴應用這些規則來轉換為輸出列類型的欄位。

  • 同樣地,如果輸出欄位是陣列類型,且 JSON 值是 JSON 陣列,則 JSON 陣列的元素會透過遞迴應用這些規則來轉換為輸出陣列的元素。

  • 否則,如果 JSON 值是字串,則會將字串的內容饋送到欄位資料類型的輸入轉換函數。

  • 否則,JSON 值的普通文字表示會饋送到欄位資料類型的輸入轉換函數。

雖然下面的範例使用常數 JSON 值,但典型的用法是從查詢的 FROM 子句中的另一個表格橫向參考 jsonjsonb 欄位。在 FROM 子句中編寫 json_populate_record 是一個好習慣,因為所有提取的欄位都可以使用,而無需重複呼叫函數。

create type subrowtype as (d int, e text); create type myrowtype as (a int, b text[], c subrowtype);

select * from json_populate_record(null::myrowtype, '{"a": 1, "b": ["2", "a b"], "c": {"d": 4, "e": "a b c"}, "x": "foo"}')

 a |   b       |      c
---+-----------+-------------
 1 | {2,"a b"} | (4,"a b c")

jsonb_populate_record_valid ( base anyelement, from_json json ) → boolean

用於測試 jsonb_populate_record 的函數。如果輸入 jsonb_populate_record 在給定的輸入 JSON 物件中完成而沒有錯誤,則傳回 true;也就是說,它是有效的輸入,否則傳回 false

create type jsb_char2 as (a char(2));

select jsonb_populate_record_valid(NULL::jsb_char2, '{"a": "aaa"}');

 jsonb_populate_record_valid
-----------------------------
 f
(1 row)

select * from jsonb_populate_record(NULL::jsb_char2, '{"a": "aaa"}') q;

ERROR:  value too long for type character(2)

select jsonb_populate_record_valid(NULL::jsb_char2, '{"a": "aa"}');

 jsonb_populate_record_valid
-----------------------------
 t
(1 row)

select * from jsonb_populate_record(NULL::jsb_char2, '{"a": "aa"}') q;

 a
----
 aa
(1 row)

json_populate_recordset ( base anyelement, from_json json ) → setof anyelement

jsonb_populate_recordset ( base anyelement, from_json jsonb ) → setof anyelement

將物件的最上層 JSON 陣列展開為一組具有 base 引數的複合類型的列。JSON 陣列的每個元素都按照上述 json[b]_populate_record 的描述進行處理。

create type twoints as (a int, b int);

select * from json_populate_recordset(null::twoints, '[{"a":1,"b":2}, {"a":3,"b":4}]')

 a | b
---+---
 1 | 2
 3 | 4

json_to_record ( json ) → record

jsonb_to_record ( jsonb ) → record

將最上層 JSON 物件展開為具有 AS 子句定義的複合類型的列。(與所有傳回 record 的函數一樣,呼叫查詢必須使用 AS 子句明確定義記錄的結構。)輸出記錄會從 JSON 物件的欄位填入,方式與上述 json[b]_populate_record 的描述相同。由於沒有輸入記錄值,因此不符的欄位始終會填入 null 值。

create type myrowtype as (a int, b text);

select * from json_to_record('{"a":1,"b":[1,2,3],"c":[1,2,3],"e":"bar","r": {"a": 123, "b": "a b c"}}') as x(a int, b text, c int[], d text, r myrowtype)

 a |    b    |    c    | d |       r
---+---------+---------+---+---------------
 1 | [1,2,3] | {1,2,3} |   | (123,"a b c")

json_to_recordset ( json ) → setof record

jsonb_to_recordset ( jsonb ) → setof record

將最上層的 JSON 物件陣列展開為一組資料列,這些資料列具有由 AS 子句定義的複合類型。(如同所有回傳 record 的函數一樣,呼叫查詢必須使用 AS 子句明確定義記錄的結構。)JSON 陣列中的每個元素都會以與 json[b]_populate_record 相同的方式處理,如上所述。

select * from json_to_recordset('[{"a":1,"b":"foo"}, {"a":"2","c":"bar"}]') as x(a int, b text)

 a |  b
---+-----
 1 | foo
 2 |

jsonb_set ( target jsonb, path text[], new_value jsonb [, create_if_missing boolean ] ) → jsonb

回傳 target,其中由 path 指定的項目會被 new_value 取代,或者如果 create_if_missing 為 true(預設值),且由 path 指定的項目不存在,則會加入 new_value。路徑中所有先前的步驟都必須存在,否則 target 將保持不變。如同路徑導向運算子一樣,出現在 path 中的負整數會從 JSON 陣列的末尾開始計數。如果最後一個路徑步驟是超出範圍的陣列索引,且 create_if_missing 為 true,則如果索引為負數,則新值會加入陣列的開頭,如果索引為正數,則會加入陣列的末尾。

jsonb_set('[{"f1":1,"f2":null},2,null,3]', '{0,f1}', '[2,3,4]', false)[{"f1": [2, 3, 4], "f2": null}, 2, null, 3]

jsonb_set('[{"f1":1,"f2":null},2]', '{0,f3}', '[2,3,4]')[{"f1": 1, "f2": null, "f3": [2, 3, 4]}, 2]

jsonb_set_lax ( target jsonb, path text[], new_value jsonb [, create_if_missing boolean [, null_value_treatment text ]] ) → jsonb

如果 new_value 不是 NULL,則其行為與 jsonb_set 相同。否則,其行為取決於 null_value_treatment 的值,該值必須是 'raise_exception''use_json_null''delete_key''return_target' 其中之一。預設值為 'use_json_null'

jsonb_set_lax('[{"f1":1,"f2":null},2,null,3]', '{0,f1}', null)[{"f1": null, "f2": null}, 2, null, 3]

jsonb_set_lax('[{"f1":99,"f2":null},2]', '{0,f3}', null, true, 'return_target')[{"f1": 99, "f2": null}, 2]

jsonb_insert ( target jsonb, path text[], new_value jsonb [, insert_after boolean ] ) → jsonb

回傳插入了 new_valuetarget。如果由 path 指定的項目是陣列元素,如果 insert_after 為 false(預設值),則 new_value 將插入該項目之前,如果 insert_after 為 true,則插入該項目之後。如果由 path 指定的項目是物件欄位,則僅當物件尚未包含該鍵時,才會插入 new_value。路徑中所有先前的步驟都必須存在,否則 target 將保持不變。如同路徑導向運算子一樣,出現在 path 中的負整數會從 JSON 陣列的末尾開始計數。如果最後一個路徑步驟是超出範圍的陣列索引,則如果索引為負數,則新值會加入陣列的開頭,如果索引為正數,則會加入陣列的末尾。

jsonb_insert('{"a": [0,1,2]}', '{a, 1}', '"new_value"'){"a": [0, "new_value", 1, 2]}

jsonb_insert('{"a": [0,1,2]}', '{a, 1}', '"new_value"', true){"a": [0, 1, "new_value", 2]}

json_strip_nulls ( json ) → json

jsonb_strip_nulls ( jsonb ) → jsonb

從給定的 JSON 值中遞迴刪除所有具有空值的物件欄位。不是物件欄位的空值保持不變。

json_strip_nulls('[{"f1":1, "f2":null}, 2, null, 3]')[{"f1":1},2,null,3]

jsonb_path_exists ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ]] ) → boolean

檢查 JSON 路徑是否為指定的 JSON 值傳回任何項目。(這僅適用於 SQL 標準 JSON 路徑表達式,而不適用於 述詞檢查表達式,因為這些表達式始終會傳回一個值。)如果指定了 vars 引數,則它必須是 JSON 物件,並且其欄位提供命名值以替換為 jsonpath 表達式。如果指定了 silent 引數並且為 true,則該函數會抑制與 @?@@ 運算子相同的錯誤。

jsonb_path_exists('{"a":[1,2,3,4,5]}', '$.a[*] ? (@ >= $min && @ <= $max)', '{"min":2, "max":4}')t

jsonb_path_match ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ]] ) → boolean

傳回指定 JSON 值的 JSON 路徑述詞檢查結果。(這僅適用於 述詞檢查表達式,而不適用於 SQL 標準 JSON 路徑表達式,因為如果路徑結果不是單一布林值,則它會失敗或傳回 NULL。)可選的 varssilent 引數的作用與 jsonb_path_exists 相同。

jsonb_path_match('{"a":[1,2,3,4,5]}', 'exists($.a[*] ? (@ >= $min && @ <= $max))', '{"min":2, "max":4}')t

jsonb_path_query ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ]] ) → setof jsonb

傳回指定 JSON 值的 JSON 路徑所傳回的所有 JSON 項目。對於 SQL 標準的 JSON 路徑表達式,它會傳回從 target 選取的 JSON 值。對於述詞檢查表達式,它會傳回述詞檢查的結果:truefalsenull。選擇性的 varssilent 引數的作用與 jsonb_path_exists 相同。

select * from jsonb_path_query('{"a":[1,2,3,4,5]}', '$.a[*] ? (@ >= $min && @ <= $max)', '{"min":2, "max":4}')

 jsonb_path_query
------------------
 2
 3
 4

jsonb_path_query_array ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ]] ) → jsonb

傳回指定 JSON 值的 JSON 路徑所傳回的所有 JSON 項目,以 JSON 陣列形式傳回。參數與 jsonb_path_query 相同。

jsonb_path_query_array('{"a":[1,2,3,4,5]}', '$.a[*] ? (@ >= $min && @ <= $max)', '{"min":2, "max":4}')[2, 3, 4]

jsonb_path_query_first ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ]] ) → jsonb

傳回指定 JSON 值的 JSON 路徑所傳回的第一個 JSON 項目,如果沒有結果則傳回 NULL。參數與 jsonb_path_query 相同。

jsonb_path_query_first('{"a":[1,2,3,4,5]}', '$.a[*] ? (@ >= $min && @ <= $max)', '{"min":2, "max":4}')2

jsonb_path_exists_tz ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ]] ) → boolean

jsonb_path_match_tz ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ]] ) → boolean

jsonb_path_query_tz ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ]] ) → setof jsonb

jsonb_path_query_array_tz ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ]] ) → jsonb

jsonb_path_query_first_tz ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ]] ) → jsonb

這些函數的作用與上述沒有 _tz 後綴的對應函數類似,但這些函數支援需要時區感知轉換的日期/時間值比較。下面的範例需要將僅包含日期的值 2015-08-02 解釋為帶有時區的時間戳記,因此結果取決於目前的 TimeZone 設定。由於這種依賴性,這些函數被標記為 stable,這意味著這些函數不能在索引中使用。它們的對應函數是 immutable,因此可以在索引中使用;但是,如果要求進行此類比較,它們將會拋出錯誤。

jsonb_path_exists_tz('["2015-08-01 12:00:00-05"]', '$[*] ? (@.datetime() < "2015-08-02".datetime())')t

jsonb_pretty ( jsonb ) → text

將給定的 JSON 值轉換為格式美觀、縮排的文字。

jsonb_pretty('[{"f1":1,"f2":null}, 2]')

[
    {
        "f1": 1,
        "f2": null
    },
    2
]

json_typeof ( json ) → text

jsonb_typeof ( jsonb ) → text

以文字字串的形式傳回最上層 JSON 值的類型。可能的類型有 objectarraystringnumberbooleannull。(null 結果不應與 SQL NULL 混淆;請參閱範例。)

json_typeof('-123.4')number

json_typeof('null'::json)null

json_typeof(NULL::json) IS NULLt


9.16.2. SQL/JSON 路徑語言 #

SQL/JSON 路徑表達式指定要從 JSON 值中擷取的項目,類似於用於存取 XML 內容的 XPath 表達式。在 PostgreSQL 中,路徑表達式以 jsonpath 資料類型實作,並且可以使用第 8.14.7 節中描述的任何元素。

JSON 查詢函數和運算子將提供的路徑表達式傳遞給路徑引擎以進行評估。如果表達式與查詢的 JSON 資料匹配,則會傳回對應的 JSON 項目或項目集。如果沒有匹配項,則結果將為 NULLfalse 或錯誤,具體取決於函數。路徑表達式以 SQL/JSON 路徑語言編寫,並且可以包含算術表達式和函數。

路徑表達式包含一個由 jsonpath 資料類型所允許的元素序列。路徑表達式通常從左到右求值,但您可以使用括號來更改運算順序。如果求值成功,則會產生一個 JSON 項目序列,並且求值結果會傳回給完成指定計算的 JSON 查詢函數。

若要引用正在查詢的 JSON 值(上下文項目),請在路徑表達式中使用 $ 變數。路徑的第一個元素必須始終是 $。它可以後跟一個或多個存取器運算子,這些運算子逐層下降 JSON 結構,以檢索上下文項目的子項目。每個存取器運算子都會作用於前一個求值步驟的結果,從每個輸入項目產生零個、一個或多個輸出項目。

例如,假設您有一些來自 GPS 追蹤器的 JSON 資料,您想進行解析,例如:

SELECT '{
  "track": {
    "segments": [
      {
        "location":   [ 47.763, 13.4034 ],
        "start time": "2018-10-14 10:05:14",
        "HR": 73
      },
      {
        "location":   [ 47.706, 13.2635 ],
        "start time": "2018-10-14 10:39:21",
        "HR": 135
      }
    ]
  }
}' AS json \gset

(可以將上面的範例複製並貼到 psql 中,以便為以下範例進行設定。然後,psql 會將 :'json' 展開為一個適當引用的字串常數,其中包含 JSON 值。)

若要檢索可用的追蹤路段,您需要使用 .key 存取器運算子來下降到周圍的 JSON 物件,例如:

=> select jsonb_path_query(:'json', '$.track.segments');
                                                                         jsonb_path_query
-----------------------------------------------------------​-----------------------------------------------------------​---------------------------------------------
 [{"HR": 73, "location": [47.763, 13.4034], "start time": "2018-10-14 10:05:14"}, {"HR": 135, "location": [47.706, 13.2635], "start time": "2018-10-14 10:39:21"}]

若要檢索陣列的內容,通常使用 [*] 運算子。以下範例將傳回所有可用追蹤路段的位置座標:

=> select jsonb_path_query(:'json', '$.track.segments[*].location');
 jsonb_path_query
-------------------
 [47.763, 13.4034]
 [47.706, 13.2635]

在這裡,我們從整個 JSON 輸入值 ($) 開始,然後 .track 存取器選擇與 "track" 物件金鑰相關聯的 JSON 物件,然後 .segments 存取器選擇與該物件中 "segments" 金鑰相關聯的 JSON 陣列,然後 [*] 存取器選擇該陣列的每個元素(產生一系列項目),然後 .location 存取器選擇與每個物件中 "location" 金鑰相關聯的 JSON 陣列。在本範例中,每個物件都有一個 "location" 金鑰;但如果其中任何一個沒有,則 .location 存取器只會產生該輸入項目的沒有輸出。

若要僅傳回第一個路段的座標,您可以在 [] 存取器運算子中指定對應的下標。回想一下,JSON 陣列索引是從 0 開始的:

=> select jsonb_path_query(:'json', '$.track.segments[0].location');
 jsonb_path_query
-------------------
 [47.763, 13.4034]

每個路徑求值步驟的結果都可以由 第 9.16.2.3 節中列出的 jsonpath 運算子和方法之一或多個進行處理。每個方法名稱前面必須加上一個點。例如,您可以取得陣列的大小:

=> select jsonb_path_query(:'json', '$.track.segments.size()');
 jsonb_path_query
------------------
 2

以下第 9.16.2.3 節中提供了在路徑表達式中使用 jsonpath 運算子和方法的更多範例。

路徑還可以包含過濾器表達式,其工作方式類似於 SQL 中的 WHERE 子句。過濾器表達式以問號開頭,並在括號中提供一個條件:

? (condition)

過濾器表達式必須寫在它們應用的路徑求值步驟之後。該步驟的結果會被過濾,僅包含滿足所提供條件的項目。SQL/JSON 定義了三值邏輯,因此條件可以產生 truefalseunknownunknown 值的作用與 SQL NULL 相同,並且可以使用 is unknown 述詞進行測試。進一步的路徑求值步驟僅使用過濾器表達式傳回 true 的那些項目。

表 9.51中列出了可在過濾器表達式中使用的函數和運算子。在過濾器表達式中,@ 變數表示正在考慮的值(即,先前路徑步驟的一個結果)。您可以在 @ 之後編寫存取器運算子來檢索元件項目。

例如,假設您想要檢索所有高於 130 的心率值。您可以按如下方式實現此目的:

=> select jsonb_path_query(:'json', '$.track.segments[*].HR ? (@ > 130)');
 jsonb_path_query
------------------
 135

若要取得具有這些值的路段的開始時間,您必須先過濾掉不相關的路段,然後再選擇開始時間,因此過濾器表達式會應用於上一步,並且條件中使用的路徑是不同的:

=> select jsonb_path_query(:'json', '$.track.segments[*] ? (@.HR > 130)."start time"');
   jsonb_path_query
-----------------------
 "2018-10-14 10:39:21"

如果需要,您可以按順序使用多個過濾器表達式。以下範例選擇包含具有相關座標和高心率值的位置的所有路段的開始時間:

=> select jsonb_path_query(:'json', '$.track.segments[*] ? (@.location[1] < 13.4) ? (@.HR > 130)."start time"');
   jsonb_path_query
-----------------------
 "2018-10-14 10:39:21"

也允許在不同的巢狀層級使用過濾器表達式。以下範例首先按位置過濾所有路段,然後傳回這些路段的高心率值(如果可用):

=> select jsonb_path_query(:'json', '$.track.segments[*] ? (@.location[1] < 13.4).HR ? (@ > 130)');
 jsonb_path_query
------------------
 135

您也可以在彼此內部巢狀過濾器表達式。此範例傳回追蹤的大小(如果它包含任何具有高心率值的路段),否則傳回一個空序列:

=> select jsonb_path_query(:'json', '$.track ? (exists(@.segments[*] ? (@.HR > 130))).segments.size()');
 jsonb_path_query
------------------
 2

9.16.2.1. 與 SQL 標準的偏差 #

PostgreSQL 的 SQL/JSON 路徑語言實作與 SQL/JSON 標準有以下偏差。

9.16.2.1.1. 布林述詞檢查表達式 #

作為 SQL 標準的擴充,PostgreSQL 路徑表達式可以是布林述詞,而 SQL 標準僅允許過濾器中的述詞。雖然 SQL 標準路徑表達式會傳回查詢的 JSON 值的相關元素,但述詞檢查表達式會傳回述詞的單個三值結果:truefalseunknown。例如,我們可以編寫此 SQL 標準過濾器表達式:

=> select jsonb_path_query(:'json', '$.track.segments ?(@[*].HR > 130)');
                                jsonb_path_query
-----------------------------------------------------------​----------------------
 {"HR": 135, "location": [47.706, 13.2635], "start time": "2018-10-14 10:39:21"}

類似的述詞檢查表達式只會傳回 true,表示存在相符項:

=> select jsonb_path_query(:'json', '$.track.segments[*].HR > 130');
 jsonb_path_query
------------------
 true

注意

@@ 運算子(和 jsonb_path_match 函數)需要述詞檢查表達式,並且不應與 @? 運算子(或 jsonb_path_exists 函數)一起使用。

9.16.2.1.2. 正則表達式解釋 #

第 9.16.2.4 節中描述的 like_regex 過濾器中使用的正則表達式模式的解釋存在細微差異。

9.16.2.2. 嚴格和寬鬆模式 #

當您查詢 JSON 資料時,路徑表達式可能與實際的 JSON 資料結構不符。嘗試存取物件的不存在的成員或陣列的元素被定義為結構錯誤。SQL/JSON 路徑表達式有兩種處理結構錯誤的模式:

  • lax (預設) — 路徑引擎會隱式地將查詢到的資料調整為指定的路徑。任何無法按照下述方式修正的結構性錯誤都會被抑制,產生不匹配的結果。

  • strict — 如果發生結構性錯誤,則會引發錯誤。

當 JSON 資料不符合預期 schema 時,Lax 模式有助於匹配 JSON 文件和路徑表達式。如果運算元不符合特定操作的要求,則可以將其自動包裝為 SQL/JSON 陣列,或通過將其元素轉換為 SQL/JSON 序列來解包,然後再執行操作。此外,比較運算符在 lax 模式下會自動解包其運算元,因此您可以直接比較 SQL/JSON 陣列。大小為 1 的陣列被認為等於其唯一元素。在以下情況下,不會執行自動解包:

  • 路徑表達式包含 type()size() 方法,這些方法分別傳回陣列中的類型和元素數量。

  • 查詢的 JSON 資料包含巢狀陣列。在這種情況下,只會解包最外層的陣列,而所有內層陣列保持不變。因此,隱式解包在每個路徑評估步驟中只能向下執行一個層級。

例如,在查詢上面列出的 GPS 資料時,您可以使用 lax 模式,無需考慮它儲存的是一個 segments 陣列的事實。

=> select jsonb_path_query(:'json', 'lax $.track.segments.location');
 jsonb_path_query
-------------------
 [47.763, 13.4034]
 [47.706, 13.2635]

在 strict 模式下,指定的路徑必須完全匹配查詢的 JSON 文件的結構,因此使用此路徑表達式會導致錯誤。

=> select jsonb_path_query(:'json', 'strict $.track.segments.location');
ERROR:  jsonpath member accessor can only be applied to an object

要獲得與 lax 模式相同的結果,您必須顯式地解包 segments 陣列。

=> select jsonb_path_query(:'json', 'strict $.track.segments[*].location');
 jsonb_path_query
-------------------
 [47.763, 13.4034]
 [47.706, 13.2635]

lax 模式的解包行為可能會導致令人驚訝的結果。例如,以下使用 .** 存取器的查詢會選擇每個 HR 值兩次。

=> select jsonb_path_query(:'json', 'lax $.**.HR');
 jsonb_path_query
------------------
 73
 135
 73
 135

發生這種情況的原因是 .** 存取器同時選擇 segments 陣列及其每個元素,而 .HR 存取器在使用 lax 模式時會自動解包陣列。為了避免令人驚訝的結果,我們建議僅在 strict 模式下使用 .** 存取器。以下查詢僅選擇每個 HR 值一次。

=> select jsonb_path_query(:'json', 'strict $.**.HR');
 jsonb_path_query
------------------
 73
 135

陣列的解包也可能導致意外的結果。考慮這個例子,它選擇了所有的 location 陣列。

=> select jsonb_path_query(:'json', 'lax $.track.segments[*].location');
 jsonb_path_query
-------------------
 [47.763, 13.4034]
 [47.706, 13.2635]
(2 rows)

正如預期的那樣,它傳回完整的陣列。但是,應用篩選表達式會導致陣列被解包以評估每個項目,只傳回與表達式匹配的項目。

=> select jsonb_path_query(:'json', 'lax $.track.segments[*].location ?(@[*] > 15)');
 jsonb_path_query
------------------
 47.763
 47.706
(2 rows)

儘管完整的陣列是由路徑表達式選定的。使用 strict 模式來恢復選擇陣列。

=> select jsonb_path_query(:'json', 'strict $.track.segments[*].location ?(@[*] > 15)');
 jsonb_path_query
-------------------
 [47.763, 13.4034]
 [47.706, 13.2635]
(2 rows)

9.16.2.3. SQL/JSON 路徑運算符和方法 #

Table 9.50 顯示了 jsonpath 中可用的運算符和方法。請注意,雖然一元運算符和方法可以應用於來自先前路徑步驟的多個值,但二元運算符(加法等)只能應用於單個值。在 lax 模式下,應用於陣列的方法將對陣列中的每個值執行。例外情況是 .type().size(),它們應用於陣列本身。

Table 9.50. jsonpath 運算符和方法

運算符/方法

描述

範例

number + numbernumber

加法

jsonb_path_query('[2]', '$[0] + 3')5

+ numbernumber

一元加號(無操作);與加法不同,它可以迭代多個值

jsonb_path_query_array('{"x": [2,3,4]}', '+ $.x')[2, 3, 4]

number - numbernumber

減法

jsonb_path_query('[2]', '7 - $[0]')5

- numbernumber

否定;與減法不同,它可以迭代多個值

jsonb_path_query_array('{"x": [2,3,4]}', '- $.x')[-2, -3, -4]

number * numbernumber

乘法

jsonb_path_query('[4]', '2 * $[0]')8

number / numbernumber

除法

jsonb_path_query('[8.5]', '$[0] / 2')4.2500000000000000

number % numbernumber

模數(餘數)

jsonb_path_query('[32]', '$[0] % 10')2

value . type()string

JSON 項目的類型(請參閱 json_typeof

jsonb_path_query_array('[1, "2", {}]', '$[*].type()')["number", "string", "object"]

value . size()number

JSON 項目的尺寸(陣列元素的數量,如果不是陣列則為 1)

jsonb_path_query('{"m": [11, 15]}', '$.m.size()')2

value . boolean()boolean

從 JSON 布林值、數字或字串轉換而來的布林值

jsonb_path_query_array('[1, "yes", false]', '$[*].boolean()')[true, true, false]

value . string()string

從 JSON 布林值、數字、字串或日期時間轉換而來的字串值

jsonb_path_query_array('[1.23, "xyz", false]', '$[*].string()')["1.23", "xyz", "false"]

jsonb_path_query('"2023-08-15 12:34:56"', '$.timestamp().string()')"2023-08-15T12:34:56"

value . double()number

從 JSON 數字或字串轉換而來的近似浮點數

jsonb_path_query('{"len": "1.9"}', '$.len.double() * 2')3.8

number . ceiling()number

大於或等於給定數字的最近整數

jsonb_path_query('{"h": 1.3}', '$.h.ceiling()')2

number . floor()number

小於或等於給定數字的最近整數

jsonb_path_query('{"h": 1.7}', '$.h.floor()')1

number . abs()number

給定數字的絕對值

jsonb_path_query('{"z": -0.3}', '$.z.abs()')0.3

value . bigint()bigint

從 JSON 數字或字串轉換而來的大整數值

jsonb_path_query('{"len": "9876543219"}', '$.len.bigint()')9876543219

value . decimal( [ precision [ , scale ] ] )decimal

從 JSON 數字或字串轉換而來的四捨五入小數值(precisionscale 必須為整數值)

jsonb_path_query('1234.5678', '$.decimal(6, 2)')1234.57

value . integer()integer

從 JSON 數字或字串轉換而來的整數值

jsonb_path_query('{"len": "12345"}', '$.len.integer()')12345

value . number()numeric

從 JSON 數字或字串轉換而來的數值

jsonb_path_query('{"len": "123.45"}', '$.len.number()')123.45

string . datetime()datetime_type (參閱說明)

從字串轉換而來的日期/時間值

jsonb_path_query('["2015-8-1", "2015-08-12"]', '$[*] ? (@.datetime() < "2015-08-2".datetime())')"2015-8-1"

string . datetime(template)datetime_type (參閱說明)

使用指定的 to_timestamp 樣板從字串轉換而來的日期/時間值

jsonb_path_query_array('["12:30", "18:40"]', '$[*].datetime("HH24:MI")')["12:30:00", "18:40:00"]

string . date()date

從字串轉換而來的日期值

jsonb_path_query('"2023-08-15"', '$.date()')"2023-08-15"

string . time()time without time zone

從字串轉換而來的無時區時間值

jsonb_path_query('"12:34:56"', '$.time()')"12:34:56"

string . time(precision)time without time zone

從字串轉換而來的無時區時間值,小數秒調整為給定的精度

jsonb_path_query('"12:34:56.789"', '$.time(2)')"12:34:56.79"

string . time_tz()time with time zone

從字串轉換而來的有時區時間值

jsonb_path_query('"12:34:56 +05:30"', '$.time_tz()')"12:34:56+05:30"

string . time_tz(precision)time with time zone

從字串轉換而來的有時區時間值,小數秒調整為給定的精度

jsonb_path_query('"12:34:56.789 +05:30"', '$.time_tz(2)')"12:34:56.79+05:30"

string . timestamp()timestamp without time zone

從字串轉換而來的無時區時間戳記值

jsonb_path_query('"2023-08-15 12:34:56"', '$.timestamp()')"2023-08-15T12:34:56"

string . timestamp(precision)timestamp without time zone

從字串轉換而來的無時區時間戳記值,小數秒調整為給定的精度

jsonb_path_query('"2023-08-15 12:34:56.789"', '$.timestamp(2)')"2023-08-15T12:34:56.79"

string . timestamp_tz()timestamp with time zone

從字串轉換而來的有時區時間戳記值

jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.timestamp_tz()')"2023-08-15T12:34:56+05:30"

string . timestamp_tz(precision)timestamp with time zone

從字串轉換而來的有時區時間戳記值,小數秒調整為給定的精度

jsonb_path_query('"2023-08-15 12:34:56.789 +05:30"', '$.timestamp_tz(2)')"2023-08-15T12:34:56.79+05:30"

object . keyvalue()array

物件的鍵值對,表示為包含三個欄位的物件陣列:"key""value""id""id" 是鍵值對所屬物件的唯一識別符

jsonb_path_query_array('{"x": "20", "y": 32}', '$.keyvalue()')[{"id": 0, "key": "x", "value": "20"}, {"id": 0, "key": "y", "value": 32}]


注意

datetime()datetime(template) 方法的結果類型可以是 datetimetztimetimestamptztimestamp。這兩個方法都會動態決定其結果類型。

datetime() 方法會依序嘗試將其輸入字串與 datetimetztimetimestamptztimestamp 的 ISO 格式進行匹配。它會在第一個匹配的格式上停止,並發出對應的資料類型。

datetime(template) 方法根據提供的樣板字串中使用的欄位來決定結果類型。

datetime()datetime(template) 方法使用與 to_timestamp SQL 函數相同的解析規則(請參閱第 9.8 節),但有三個例外。首先,這些方法不允許不匹配的樣板模式。第二,樣板字串中僅允許以下分隔符號:減號、句點、斜線(斜杠)、逗號、單引號、分號、冒號和空格。第三,樣板字串中的分隔符號必須與輸入字串完全匹配。

如果需要比較不同的日期/時間類型,會套用隱含轉換。 date 值可以轉換為 timestamptimestamptztimestamp 可以轉換為 timestamptztime 可以轉換為 timetz。然而,除了第一種轉換外,其他轉換都取決於目前的 TimeZone 設定,因此只能在感知時區的 jsonpath 函數中執行。同樣地,其他將字串轉換為日期/時間類型的方法也會進行這種轉換,這可能涉及到目前的 TimeZone 設定。因此,這些轉換也只能在感知時區的 jsonpath 函數中執行。

表 9.51 顯示了可用的過濾器運算式元素。

表 9.51. jsonpath 過濾器運算式元素

述詞/值

描述

範例

value == valueboolean

相等比較(此運算子以及其他比較運算子適用於所有 JSON 純量值)

jsonb_path_query_array('[1, "a", 1, 3]', '$[*] ? (@ == 1)')[1, 1]

jsonb_path_query_array('[1, "a", 1, 3]', '$[*] ? (@ == "a")')["a"]

value != valueboolean

value <> valueboolean

不相等比較

jsonb_path_query_array('[1, 2, 1, 3]', '$[*] ? (@ != 1)')[2, 3]

jsonb_path_query_array('["a", "b", "c"]', '$[*] ? (@ <> "b")')["a", "c"]

value < valueboolean

小於比較

jsonb_path_query_array('[1, 2, 3]', '$[*] ? (@ < 2)')[1]

value <= valueboolean

小於或等於比較

jsonb_path_query_array('["a", "b", "c"]', '$[*] ? (@ <= "b")')["a", "b"]

value > valueboolean

大於比較

jsonb_path_query_array('[1, 2, 3]', '$[*] ? (@ > 2)')[3]

value >= valueboolean

大於或等於比較

jsonb_path_query_array('[1, 2, 3]', '$[*] ? (@ >= 2)')[2, 3]

trueboolean

JSON 常數 true

jsonb_path_query('[{"name": "John", "parent": false}, {"name": "Chris", "parent": true}]', '$[*] ? (@.parent == true)'){"name": "Chris", "parent": true}

falseboolean

JSON 常數 false

jsonb_path_query('[{"name": "John", "parent": false}, {"name": "Chris", "parent": true}]', '$[*] ? (@.parent == false)'){"name": "John", "parent": false}

nullvalue

JSON 常數 null (請注意,與 SQL 不同,與 null 的比較可以正常工作)

jsonb_path_query('[{"name": "Mary", "job": null}, {"name": "Michael", "job": "driver"}]', '$[*] ? (@.job == null) .name')"Mary"

boolean && booleanboolean

布林 AND

jsonb_path_query('[1, 3, 7]', '$[*] ? (@ > 1 && @ < 5)')3

boolean || booleanboolean

布林 OR

jsonb_path_query('[1, 3, 7]', '$[*] ? (@ < 1 || @ > 5)')7

! booleanboolean

布林 NOT

jsonb_path_query('[1, 3, 7]', '$[*] ? (!(@ < 5))')7

boolean is unknownboolean

測試布林條件是否為 unknown

jsonb_path_query('[-1, 2, 7, "foo"]', '$[*] ? ((@ > 0) is unknown)')"foo"

string like_regex string [ flag string ] → boolean

測試第一個運算元是否符合第二個運算元給定的正規表示式,可選擇性地使用由 flag 字元組成的字串來描述修改(請參閱章節 9.16.2.4)。

jsonb_path_query_array('["abc", "abd", "aBdC", "abdacb", "babc"]', '$[*] ? (@ like_regex "^ab.*c")')["abc", "abdacb"]

jsonb_path_query_array('["abc", "abd", "aBdC", "abdacb", "babc"]', '$[*] ? (@ like_regex "^ab.*c" flag "i")')["abc", "aBdC", "abdacb"]

string starts with stringboolean

測試第二個運算元是否為第一個運算元的初始子字串。

jsonb_path_query('["John Smith", "Mary Stone", "Bob Johnson"]', '$[*] ? (@ starts with "John")')"John Smith"

exists ( path_expression )boolean

測試路徑運算式是否符合至少一個 SQL/JSON 項目。如果路徑運算式會導致錯誤,則傳回 unknown;第二個範例使用它來避免嚴格模式下的 no-such-key 錯誤。

jsonb_path_query('{"x": [1, 2], "y": [2, 4]}', 'strict $.* ? (exists (@ ? (@[*] > 2)))')[2, 4]

jsonb_path_query_array('{"value": 41}', 'strict $ ? (exists (@.name)) .name')[]


9.16.2.4. SQL/JSON 正規表示式 #

SQL/JSON 路徑表達式允許使用 like_regex 篩選器將文字與正規表示式進行匹配。例如,以下 SQL/JSON 路徑查詢會以不區分大小寫的方式匹配陣列中所有以英文母音開頭的字串

$[*] ? (@ like_regex "^[aeiou]" flag "i")

可選的 flag 字串可以包含以下一個或多個字元:i 表示不區分大小寫匹配,m 允許 ^$ 在換行符處匹配,s 允許 . 匹配換行符,以及 q 引用整個模式(將行為簡化為簡單的子字串匹配)。

SQL/JSON 標準從 LIKE_REGEX 運算子借用了正規表示式的定義,而 LIKE_REGEX 運算子又使用了 XQuery 標準。PostgreSQL 目前不支援 LIKE_REGEX 運算子。因此,like_regex 篩選器是使用 第 9.7.3 節 中描述的 POSIX 正規表示式引擎實作的。這導致與標準 SQL/JSON 行為存在各種微小的差異,這些差異在 第 9.7.3.8 節 中進行了編目。但是請注意,那裡描述的旗標字母不相容性不適用於 SQL/JSON,因為它會轉換 XQuery 旗標字母以匹配 POSIX 引擎期望的內容。

請記住,like_regex 的 pattern 參數是一個 JSON 路徑字串常值,根據 第 8.14.7 節 中給出的規則編寫。這尤其意味著您想在正規表示式中使用的任何反斜線都必須加倍。例如,要匹配僅包含數字的根文件字串值

$.* ? (@ like_regex "^\\d+$")

9.16.3. SQL/JSON 查詢函數 #

表格 9.52 中描述的 SQL/JSON 函數 JSON_EXISTS()JSON_QUERY()JSON_VALUE() 可用於查詢 JSON 文件。這些函數中的每一個都將 path_expression (SQL/JSON 路徑查詢) 應用於 context_item (文件)。有關 path_expression 可以包含的內容的更多詳細資訊,請參閱 第 9.16.2 節path_expression 也可以引用變數,這些變數的值在其各自的名稱中由每個函數支援的 PASSING 子句指定。context_item 可以是 jsonb 值或可以成功轉換為 jsonb 的字元串。

表格 9.52. SQL/JSON 查詢函數

函式簽章

描述

範例

JSON_EXISTS (
context_item, path_expression
[ PASSING { value AS varname } [, ...]]
[{ TRUE | FALSE | UNKNOWN | ERROR } ON ERROR ]) → boolean

  • 如果應用於 context_item 的 SQL/JSON path_expression 產生任何項目,則傳回 true,否則傳回 false。

  • ON ERROR 子句指定在 path_expression 評估期間發生錯誤時的行為。指定 ERROR 會導致擲回帶有適當訊息的錯誤。其他選項包括傳回 booleanFALSETRUE,或實際上是 SQL NULL 的值 UNKNOWN。未指定 ON ERROR 子句時的預設值是傳回 booleanFALSE

範例

JSON_EXISTS(jsonb '{"key1": [1,2,3]}', 'strict $.key1[*] ? (@ > $x)' PASSING 2 AS x)t

JSON_EXISTS(jsonb '{"a": [1,2,3]}', 'lax $.a[5]' ERROR ON ERROR)f

JSON_EXISTS(jsonb '{"a": [1,2,3]}', 'strict $.a[5]' ERROR ON ERROR)

ERROR:  jsonpath array subscript is out of bounds

JSON_QUERY (
context_item, path_expression
[ PASSING { value AS varname } [, ...]]
[ RETURNING data_type [ FORMAT JSON [ ENCODING UTF8 ] ] ]
[ { WITHOUT | WITH { CONDITIONAL | [UNCONDITIONAL] } } [ ARRAY ] WRAPPER ]
[ { KEEP | OMIT } QUOTES [ ON SCALAR STRING ] ]
[ { ERROR | NULL | EMPTY { [ ARRAY ] | OBJECT } | DEFAULT expression } ON EMPTY ]
[ { ERROR | NULL | EMPTY { [ ARRAY ] | OBJECT } | DEFAULT expression } ON ERROR ]) → jsonb

  • 傳回將 SQL/JSON path_expression 應用於 context_item 的結果。

  • 預設情況下,結果會以 jsonb 型別的值傳回,但可以使用 RETURNING 子句以它可以成功強制轉換的其他型別傳回。

  • 如果路徑表達式可能會傳回多個值,則可能需要使用 WITH WRAPPER 子句包裝這些值,使其成為有效的 JSON 字串,因為預設行為是不包裝它們,就像指定了 WITHOUT WRAPPER 一樣。WITH WRAPPER 子句預設被認為是 WITH UNCONDITIONAL WRAPPER,這意味著即使是單個結果值也會被包裝。要僅在存在多個值時套用包裝器,請指定 WITH CONDITIONAL WRAPPER。如果在結果中獲取多個值,並且指定了 WITHOUT WRAPPER,則會將其視為錯誤。

  • 如果結果是純量字串,則預設情況下,傳回的值將被引號包圍,使其成為有效的 JSON 值。可以透過指定 KEEP QUOTES 來明確指定它。相反,可以透過指定 OMIT QUOTES 來省略引號。為了確保結果是有效的 JSON 值,在同時指定 WITH WRAPPER 時,不能指定 OMIT QUOTES

  • ON EMPTY 子句指定評估 path_expression 產生空集合時的行為。ON ERROR 子句指定在評估 path_expression 時、將結果值強制轉換為 RETURNING 型別時,或者在 path_expression 評估傳回空集合時評估 ON EMPTY 表達式時發生錯誤時的行為。

  • 對於 ON EMPTYON ERROR,指定 ERROR 會導致擲回帶有適當訊息的錯誤。其他選項包括傳回 SQL NULL、空陣列 (EMPTY [ARRAY])、空物件 (EMPTY OBJECT) 或可以強制轉換為 jsonb 或 RETURNING 中指定的型別的使用者指定表達式 (DEFAULT expression)。未指定 ON EMPTYON ERROR 時的預設值是傳回 SQL NULL 值。

範例

JSON_QUERY(jsonb '[1,[2,3],null]', 'lax $[*][$off]' PASSING 1 AS off WITH CONDITIONAL WRAPPER)3

JSON_QUERY(jsonb '{"a": "[1, 2]"}', 'lax $.a' OMIT QUOTES)[1, 2]

JSON_QUERY(jsonb '{"a": "[1, 2]"}', 'lax $.a' RETURNING int[] OMIT QUOTES ERROR ON ERROR)

ERROR:  malformed array literal: "[1, 2]"
DETAIL:  Missing "]" after array dimensions.

JSON_VALUE (
context_item, path_expression
[ PASSING { value AS varname } [, ...]]
[ RETURNING data_type ]
[ { ERROR | NULL | DEFAULT expression } ON EMPTY ]
[ { ERROR | NULL | DEFAULT expression } ON ERROR ]) → text

  • 傳回將 SQL/JSON path_expression 應用於 context_item 的結果。

  • 僅當預期提取的值是單一值時才使用 JSON_VALUE()SQL/JSON純量項目;獲取多個值將被視為錯誤。如果您預期提取的值可能是物件或陣列,請改用 JSON_QUERY 函數。

  • 預設情況下,結果(必須是單一純量值)會以 text 型別的值傳回,但可以使用 RETURNING 子句以它可以成功強制轉換的其他型別傳回。

  • ON ERRORON EMPTY 子句具有與 JSON_QUERY 的描述中提到的相似語意,只是傳回以代替擲回錯誤的值集合不同。

  • 請注意,JSON_VALUE 傳回的純量字串始終會移除其引號,相當於在 JSON_QUERY 中指定 OMIT QUOTES

範例

JSON_VALUE(jsonb '"123.45"', '$' RETURNING float)123.45

JSON_VALUE(jsonb '"03:04 2015-02-01"', '$.datetime("HH24:MI YYYY-MM-DD")' RETURNING date)2015-02-01

JSON_VALUE(jsonb '[1,2]', 'strict $[$off]' PASSING 1 as off)2

JSON_VALUE(jsonb '[1,2]', 'strict $[*]' DEFAULT 9 ON ERROR)9


注意

如果 context_item 運算式還不是 jsonb 類型,則會透過隱含轉換將其轉換為 jsonb。但是請注意,在此轉換期間發生的任何解析錯誤都會無條件拋出,也就是說,不會根據(指定的或隱含的)ON ERROR 子句處理。

注意

如果 path_expression 傳回 JSON null,則 JSON_VALUE() 會傳回 SQL NULL,而 JSON_QUERY() 會原樣傳回 JSON null

9.16.4. JSON_TABLE #

JSON_TABLE 是一個 SQL/JSON 函數,用於查詢JSON資料並將結果呈現為關聯式檢視,可以像存取常規 SQL 表一樣存取。您可以在 SELECTUPDATEDELETEFROM 子句中使用 JSON_TABLE,並在 MERGE 陳述式中作為資料來源。

以 JSON 資料作為輸入,JSON_TABLE 使用 JSON 路徑運算式來提取提供的資料的一部分,以用作建構檢視的資料列模式。資料列模式給出的每個 SQL/JSON 值都充當建構檢視中單獨資料列的來源。

為了將資料列模式分割為欄位,JSON_TABLE 提供了 COLUMNS 子句,用於定義建立的檢視的綱要。對於每個欄位,可以指定單獨的 JSON 路徑運算式,以針對資料列模式進行評估,以取得一個 SQL/JSON 值,該值將成為給定輸出資料列中指定欄位的值。

可以使用 NESTED PATH 子句提取儲存在資料列模式的巢狀層級的 JSON 資料。每個 NESTED PATH 子句可用於使用資料列模式的巢狀層級的資料來產生一個或多個欄位。可以使用類似於頂層 COLUMNS 子句的 COLUMNS 子句來指定這些欄位。由 NESTED COLUMNS 建構的資料列稱為子資料列,並與從父 COLUMNS 子句中指定的欄位建構的資料列聯結,以取得最終檢視中的資料列。子欄位本身可能包含 NESTED PATH 規格,從而允許提取位於任意巢狀層級的資料。由同一層級的多個 NESTED PATH 產生的欄位被認為是彼此的同層級,並且它們在與父資料列聯結後的資料列使用 UNION 組合。

JSON_TABLE 產生的資料列以橫向聯結的方式聯結到產生它們的資料列,因此您不必顯式地將建構的檢視與持有JSON資料的原始表聯結。

語法為

JSON_TABLE (
    context_item, path_expression [ AS json_path_name ] [ PASSING { value AS varname } [, ...] ]
    COLUMNS ( json_table_column [, ...] )
    [ { ERROR | EMPTY [ARRAY]} ON ERROR ]
)


where json_table_column is:

  name FOR ORDINALITY
  | name type
        [ FORMAT JSON [ENCODING UTF8]]
        [ PATH path_expression ]
        [ { WITHOUT | WITH { CONDITIONAL | [UNCONDITIONAL] } } [ ARRAY ] WRAPPER ]
        [ { KEEP | OMIT } QUOTES [ ON SCALAR STRING ] ]
        [ { ERROR | NULL | EMPTY { [ARRAY] | OBJECT } | DEFAULT expression } ON EMPTY ]
        [ { ERROR | NULL | EMPTY { [ARRAY] | OBJECT } | DEFAULT expression } ON ERROR ]
  | name type EXISTS [ PATH path_expression ]
        [ { ERROR | TRUE | FALSE | UNKNOWN } ON ERROR ]
  | NESTED [ PATH ] path_expression [ AS json_path_name ] COLUMNS ( json_table_column [, ...] )

每個語法元素在下面有更詳細的描述。

context_item, path_expression [ AS json_path_name ] [ PASSING { value AS varname } [, ...]]

context_item 指定要查詢的輸入文件,path_expression 是一個 SQL/JSON 路徑運算式,用於定義查詢,json_path_namepath_expression 的可選名稱。可選的 PASSING 子句為 path_expression 中提到的變數提供資料值。使用上述元素評估輸入資料的結果稱為資料列模式,該模式用作建構檢視中資料列值的來源。

COLUMNS ( json_table_column [, ...] )

COLUMNS 子句定義了建構檢視的綱要。在此子句中,您可以指定每個欄位,以使用透過將 JSON 路徑運算式應用於資料列模式而獲得的 SQL/JSON 值來填充。json_table_column 具有以下變體

name FOR ORDINALITY

新增一個序數欄位,該欄位提供從 1 開始的循序資料列編號。每個 NESTED PATH(見下文)都為任何巢狀序數欄位取得其自己的計數器。

name type [FORMAT JSON [ENCODING UTF8]] [ PATH path_expression ]

將 SQL/JSON 值插入到檢視的輸出資料列中,該值是透過將 path_expression 應用於資料列模式後,強制轉換為指定的 type 而獲得的。

指定 FORMAT JSON 可以明確表示您期望該值是有效的 json 物件。僅當 typebpcharbyteacharacter varyingnamejsonjsonbtext 之一,或這些類型的網域時,指定 FORMAT JSON 才是有意義的。

您可以選擇指定 WRAPPERQUOTES 子句來格式化輸出。請注意,如果也指定了 OMIT QUOTES,則會覆蓋 FORMAT JSON,因為未加引號的文字不構成有效的 json 值。

您可以選擇使用 ON EMPTYON ERROR 子句來指定在 JSON 路徑評估的結果為空時,以及在 JSON 路徑評估期間或將 SQL/JSON 值強制轉換為指定類型時發生錯誤時,是否拋出錯誤或傳回指定的值。兩者的預設值都是傳回 NULL 值。

注意

此子句在內部轉換為 JSON_VALUEJSON_QUERY,並具有相同的語意。如果指定的類型不是純量類型,或者存在 FORMAT JSONWRAPPERQUOTES 子句中的任何一個,則後者是 JSON_QUERY

name type EXISTS [ PATH path_expression ]

插入一個布林值,該值是將 path_expression 套用至列模式後,強制轉換為指定的 type 後,插入到檢視表的輸出列中。

該值對應於將 PATH 表達式套用至列模式是否產生任何值。

指定的 type 應具有從 boolean 型別的強制轉換。

您可以選擇使用 ON ERROR 來指定在 JSON 路徑評估期間或將 SQL/JSON 值強制轉換為指定型別時發生錯誤時,是否要擲回錯誤或傳回指定的值。預設值是傳回布林值 FALSE

注意

此子句在內部會轉換為 JSON_EXISTS,並具有與其相同的語意。

NESTED [ PATH ] path_expression [ AS json_path_name ] COLUMNS ( json_table_column [, ...] )

從列模式的巢狀層級提取 SQL/JSON 值,產生由 COLUMNS 子句定義的一或多個欄位,並將提取的 SQL/JSON 值插入到這些欄位中。COLUMNS 子句中的 json_table_column 表達式使用與父 COLUMNS 子句中相同的語法。

NESTED PATH 語法是遞迴的,因此您可以透過在彼此之間指定多個 NESTED PATH 子句,向下移動多個巢狀層級。它允許在單個函數呼叫中解開 JSON 物件和陣列的階層,而不是在 SQL 語句中鏈接多個 JSON_TABLE 表達式。

注意

在上面描述的每個 json_table_column 變體中,如果省略 PATH 子句,則使用路徑表達式 $.name,其中 name 是提供的欄位名稱。

AS json_path_name

可選的 json_path_name 用作提供的 path_expression 的識別符。該名稱必須是唯一的,並且與欄位名稱不同。

{ ERROR | EMPTY } ON ERROR

可選的 ON ERROR 可用於指定在評估最上層 path_expression 時如何處理錯誤。 如果您希望擲回錯誤,請使用 ERROR,如果想要傳回空表格(即包含 0 列的表格),請使用 EMPTY。請注意,此子句不會影響評估欄位時發生的錯誤,對於欄位的行為取決於是否針對給定欄位指定了 ON ERROR 子句。

範例

在下面的範例中,將使用包含 JSON 資料的下列表格

CREATE TABLE my_films ( js jsonb );

INSERT INTO my_films VALUES (
'{ "favorites" : [
   { "kind" : "comedy", "films" : [
     { "title" : "Bananas",
       "director" : "Woody Allen"},
     { "title" : "The Dinner Game",
       "director" : "Francis Veber" } ] },
   { "kind" : "horror", "films" : [
     { "title" : "Psycho",
       "director" : "Alfred Hitchcock" } ] },
   { "kind" : "thriller", "films" : [
     { "title" : "Vertigo",
       "director" : "Alfred Hitchcock" } ] },
   { "kind" : "drama", "films" : [
     { "title" : "Yojimbo",
       "director" : "Akira Kurosawa" } ] }
  ] }');

以下查詢示範如何使用 JSON_TABLEmy_films 表格中的 JSON 物件轉換為檢視表,該檢視表包含原始 JSON 中包含的鍵 kindtitledirector 的欄位,以及一個序數欄位

SELECT jt.* FROM
 my_films,
 JSON_TABLE (js, '$.favorites[*]' COLUMNS (
   id FOR ORDINALITY,
   kind text PATH '$.kind',
   title text PATH '$.films[*].title' WITH WRAPPER,
   director text PATH '$.films[*].director' WITH WRAPPER)) AS jt;
 id |   kind   |             title              |             director
----+----------+--------------------------------+----------------------------------
  1 | comedy   | ["Bananas", "The Dinner Game"] | ["Woody Allen", "Francis Veber"]
  2 | horror   | ["Psycho"]                     | ["Alfred Hitchcock"]
  3 | thriller | ["Vertigo"]                    | ["Alfred Hitchcock"]
  4 | drama    | ["Yojimbo"]                    | ["Akira Kurosawa"]
(4 rows)

以下是上述查詢的修改版本,用於顯示在最上層 JSON 路徑表達式中指定的篩選器中使用 PASSING 引數,以及各個欄位的各種選項

SELECT jt.* FROM
 my_films,
 JSON_TABLE (js, '$.favorites[*] ? (@.films[*].director == $filter)'
   PASSING 'Alfred Hitchcock' AS filter, 'Vertigo' AS filter2
     COLUMNS (
     id FOR ORDINALITY,
     kind text PATH '$.kind',
     title text FORMAT JSON PATH '$.films[*].title' OMIT QUOTES,
     director text PATH '$.films[*].director' KEEP QUOTES)) AS jt;
 id |   kind   |  title  |      director
----+----------+---------+--------------------
  1 | horror   | Psycho  | "Alfred Hitchcock"
  2 | thriller | Vertigo | "Alfred Hitchcock"
(2 rows)

以下是上述查詢的修改版本,用於顯示使用 NESTED PATH 填充標題和導演欄位,說明它們如何聯結到父欄位 id 和 kind

SELECT jt.* FROM
 my_films,
 JSON_TABLE ( js, '$.favorites[*] ? (@.films[*].director == $filter)'
   PASSING 'Alfred Hitchcock' AS filter
   COLUMNS (
    id FOR ORDINALITY,
    kind text PATH '$.kind',
    NESTED PATH '$.films[*]' COLUMNS (
      title text FORMAT JSON PATH '$.title' OMIT QUOTES,
      director text PATH '$.director' KEEP QUOTES))) AS jt;
 id |   kind   |  title  |      director
----+----------+---------+--------------------
  1 | horror   | Psycho  | "Alfred Hitchcock"
  2 | thriller | Vertigo | "Alfred Hitchcock"
(2 rows)

以下是相同的查詢,但沒有根路徑中的篩選器

SELECT jt.* FROM
 my_films,
 JSON_TABLE ( js, '$.favorites[*]'
   COLUMNS (
    id FOR ORDINALITY,
    kind text PATH '$.kind',
    NESTED PATH '$.films[*]' COLUMNS (
      title text FORMAT JSON PATH '$.title' OMIT QUOTES,
      director text PATH '$.director' KEEP QUOTES))) AS jt;
 id |   kind   |      title      |      director
----+----------+-----------------+--------------------
  1 | comedy   | Bananas         | "Woody Allen"
  1 | comedy   | The Dinner Game | "Francis Veber"
  2 | horror   | Psycho          | "Alfred Hitchcock"
  3 | thriller | Vertigo         | "Alfred Hitchcock"
  4 | drama    | Yojimbo         | "Akira Kurosawa"
(5 rows)

以下顯示另一個查詢,該查詢使用不同的 JSON 物件作為輸入。它顯示了 NESTED 路徑 $.movies[*]$.books[*] 之間的 UNION「同級聯結」,以及在 NESTED 層級 (欄位 movie_idbook_idauthor_id) 使用 FOR ORDINALITY 欄位

SELECT * FROM JSON_TABLE (
'{"favorites":
    {"movies":
      [{"name": "One", "director": "John Doe"},
       {"name": "Two", "director": "Don Joe"}],
     "books":
      [{"name": "Mystery", "authors": [{"name": "Brown Dan"}]},
       {"name": "Wonder", "authors": [{"name": "Jun Murakami"}, {"name":"Craig Doe"}]}]
}}'::json, '$.favorites[*]'
COLUMNS (
  user_id FOR ORDINALITY,
  NESTED '$.movies[*]'
    COLUMNS (
    movie_id FOR ORDINALITY,
    mname text PATH '$.name',
    director text),
  NESTED '$.books[*]'
    COLUMNS (
      book_id FOR ORDINALITY,
      bname text PATH '$.name',
      NESTED '$.authors[*]'
        COLUMNS (
          author_id FOR ORDINALITY,
          author_name text PATH '$.name'))));
 user_id | movie_id | mname | director | book_id |  bname  | author_id | author_name
---------+----------+-------+----------+---------+---------+-----------+--------------
       1 |        1 | One   | John Doe |         |         |           |
       1 |        2 | Two   | Don Joe  |         |         |           |
       1 |          |       |          |       1 | Mystery |         1 | Brown Dan
       1 |          |       |          |       2 | Wonder  |         1 | Jun Murakami
       1 |          |       |          |       2 | Wonder  |         2 | Craig Doe
(5 rows)

提交更正

如果您在文件中發現任何不正確、與特定功能的體驗不符或需要進一步澄清的地方,請使用此表單來回報文件問題。