2025年9月25日: PostgreSQL 18 釋出!
支援的版本:當前 (18) / 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 空值,以及使用 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.47 顯示了可用於 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.47。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,而不是失敗。

表 9.48 所示,還有一些運算子僅適用於 jsonb第 8.14.4 節 描述瞭如何使用這些運算子有效地搜尋索引的 jsonb 資料。

表 9.48。附加 jsonb 運算子

運算子

描述

示例

jsonb @> jsonbboolean

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

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

jsonb <@ jsonbboolean

第一個 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.49 顯示了可用於構造 jsonjsonb 值的函式。此表中的某些函式具有 RETURNING 子句,該子句指定返回的資料型別。它必須是 jsonjsonbbytea、字元字串型別(textcharvarchar),或可以轉換為 json 的型別之一。預設情況下,返回 json 型別。

表 9.49。JSON 建立函式

函式

描述

示例

to_json ( anyelement ) → json

to_jsonb ( anyelement ) → jsonb

將任何 SQL 值轉換為 jsonjsonb。陣列和複合型別遞迴地轉換為 JSON 中的陣列和物件(多維陣列成為 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 陣列,後者必須是返回單個列的 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。如果指定了 ABSENT ON NULL,則 value_expression 求值為 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

將指定為 textbytea 字串(以 UTF8 編碼)的給定表示式轉換為 JSON 值。如果 expression 為 NULL,則返回一個SQL空值。如果指定了 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.50 詳細介紹了用於測試 JSON 的 SQL/JSON 工具。

表 9.50。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.51 顯示了可用於處理 jsonjsonb 值的函式。

表 9.51。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 空值在所有情況下都轉換為 SQL 空值。

  • 如果輸出列的型別為 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 的函式。如果給定輸入 JSON 物件,輸入 jsonb_populate_record 將在沒有錯誤的情況下完成,則返回 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 ( target json [,strip_in_arrays boolean ] ) → json

jsonb_strip_nulls ( target jsonb [,strip_in_arrays boolean ] ) → jsonb

遞迴地從給定 JSON 值中刪除所有具有 null 值的物件欄位。如果 strip_in_arrays 為 true(預設值為 false),則也會刪除空陣列元素。否則它們不會被刪除。裸 null 值永遠不會被刪除。

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

jsonb_strip_nulls('[1,2,null,3,4]', true);[1,2,3,4]

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 布林結果。(這僅對謂詞檢查表示式有用,對 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 設定。由於此依賴關係,這些函式被標記為穩定,這意味著這些函式不能用於索引。它們的對應函式是不可變的,因此可以用於索引;但如果要求它們進行此類比較,它們將丟擲錯誤。

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

有關在路徑表示式中使用 jsonpath 運算子和方法的更多示例,請參見下面的 第 9.16.2.3 節

路徑還可以包含篩選表示式,其工作方式類似於 SQL 中的 WHERE 子句。篩選表示式以問號開頭,並在括號中提供條件

? (condition)

篩選表示式必須緊接在其應應用的路徑評估步驟之後編寫。該步驟的結果將經過篩選,只包含滿足所提供條件的項。SQL/JSON 定義了三值邏輯,因此條件可以生成 truefalseunknownunknown 值的作用與 SQL NULL 相同,可以使用 is unknown 謂詞進行測試。進一步的路徑評估步驟只使用篩選表示式返回 true 的那些項。

可在篩選表示式中使用的函式和運算子列在 表 9.53 中。在篩選表示式中,@ 變量表示正在考慮的值(即,前一個路徑步驟的一個結果)。您可以在 @ 之後編寫訪問器運算子以檢索元件項。

例如,假設您想檢索所有高於 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 值中的相關元素,而謂詞檢查表示式返回謂詞的單個三值 jsonb 結果:truefalsenull。例如,我們可以這樣編寫 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. 正則表示式解釋 #

like_regex 篩選器中使用的正則表示式模式的解釋存在細微差別,如 第 9.16.2.4 節中所述。

9.16.2.2. 寬鬆模式和嚴格模式 #

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

  • 寬鬆模式(預設)——路徑引擎隱式地將查詢資料適應指定的路徑。任何無法按如下所述修復的結構錯誤都將被抑制,不產生匹配。

  • 嚴格模式——如果發生結構錯誤,則會引發錯誤。

當 JSON 資料不符合預期模式時,寬鬆模式有助於匹配 JSON 文件和路徑表示式。如果運算元不符合特定操作的要求,它可以透過將其元素轉換為 SQL/JSON 序列來自動封裝為 SQL/JSON 陣列,或在執行操作之前解封裝。此外,在寬鬆模式下,比較運算子會自動解封裝其運算元,因此您可以直接比較 SQL/JSON 陣列。大小為 1 的陣列被視為與其唯一元素相等。在以下情況下不執行自動解封裝

  • 路徑表示式包含 type()size() 方法,它們分別返回陣列的型別和元素數量。

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

例如,當查詢上述 GPS 資料時,在使用寬鬆模式時可以忽略它儲存一個分段陣列的事實

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

在嚴格模式下,指定的路徑必須精確匹配查詢 JSON 文件的結構,因此使用此路徑表示式將導致錯誤

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

要獲得與寬鬆模式相同的結果,您必須顯式解封裝 segments 陣列

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

寬鬆模式的解封裝行為可能導致令人驚訝的結果。例如,以下使用 .** 訪問器的查詢會選擇每個 HR 值兩次

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

這是因為 .** 訪問器會選擇 segments 陣列及其每個元素,而 .HR 訪問器在使用寬鬆模式時會自動解封裝陣列。為避免令人驚訝的結果,我們建議僅在嚴格模式下使用 .** 訪問器。以下查詢只選擇每個 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)

儘管路徑表示式選擇了完整的陣列。使用嚴格模式恢復選擇陣列

=> 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 路徑運算子和方法 #

表 9.52 顯示了 jsonpath 中可用的運算子和方法。請注意,雖然一元運算子和方法可以應用於前一個路徑步驟產生的多個值,但二元運算子(加法等)只能應用於單個值。在寬鬆模式下,應用於陣列的方法將對陣列中的每個值執行。例外是 .type().size(),它們應用於陣列本身。

表 9.52. jsonpath 運算子和方法

運算子/方法

描述

示例

數字 + 數字數字

加法。

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

+ 數字數字

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

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

數字 - 數字數字

減法。

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

- 數字數字

取反;與減法不同,這可以迭代多個值

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

數字 * 數字數字

乘法。

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

數字 / 數字數字

除法

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

數字 % 數字數字

模數(餘數)

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

. type()字串

JSON 項的型別(參見 json_typeof

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

. size()數字

JSON 項的大小(陣列元素的數量,如果不是陣列則為 1)

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

. boolean()布林值

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

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

. 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"

. double()數字

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

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

數字 . ceiling()數字

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

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

數字 . floor()數字

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

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

數字 . abs()數字

給定數字的絕對值

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

. bigint()大整數

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

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

. decimal( [ 精度 [ , 標度 ] ] )十進位制

從 JSON 數字或字串轉換的舍入十進位制值(precisionscale 必須是整數值)

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

. integer()整數

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

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

. number()數字型

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

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

字串 . datetime()日期時間型別 (參見注釋)

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

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

字串 . datetime(模板)日期時間型別 (參見注釋)

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

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

字串 . date()日期

從字串轉換的日期值

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

字串 . time()無時區時間

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

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

字串 . time(精度)無時區時間

從字串轉換的無時區時間值,分數秒調整到給定精度

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

字串 . time_tz()帶時區時間

從字串轉換的帶時區時間值

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

字串 . time_tz(精度)帶時區時間

從字串轉換的帶時區時間值,分數秒調整到給定精度

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

字串 . timestamp()無時區時間戳

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

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

字串 . timestamp(精度)無時區時間戳

從字串轉換的無時區時間戳值,分數秒調整到給定精度

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

字串 . timestamp_tz()帶時區時間戳

從字串轉換的帶時區時間戳值

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

字串 . timestamp_tz(精度)帶時區時間戳

從字串轉換的帶時區時間戳值,分數秒調整到給定精度

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

物件 . keyvalue()陣列

物件的鍵值對,表示為包含三個欄位的物件陣列:"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.53 顯示了可用的篩選表示式元素。

表 9.53. jsonpath 篩選表示式元素

謂詞/值

描述

示例

== 布林值

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

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

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

!= 布林值

<> 布林值

不相等比較

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

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

< 布林值

小於比較

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

<= 布林值

小於或等於比較

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

> 布林值

大於比較

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

>= 布林值

大於或等於比較

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

true布林值

JSON 常量 true

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

false布林值

JSON 常量 false

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

null

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

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

布林值 && 布林值布林值

布林 AND

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

布林值 || 布林值布林值

布林 OR

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

! 布林值布林值

布林 NOT

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

布林值 is unknown布林值

測試布林條件是否為 unknown

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

字串 like_regex 字串 [ flag 字串 ] → 布林值

測試第一個運算元是否與第二個運算元給定的正則表示式匹配,可選地透過 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"]

字串 starts with 字串布林值

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

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

exists ( 路徑表示式 )布林值

測試路徑表示式是否匹配至少一個 SQL/JSON 項。如果路徑表示式會導致錯誤,則返回 unknown;第二個示例使用此方法在嚴格模式下避免“無此類鍵”錯誤。

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 運算子的正則表示式定義,而該運算子又使用 XQuery 標準。PostgreSQL 目前不支援 LIKE_REGEX 運算子。因此,like_regex 篩選器是使用 第 9.7.3 節中描述的 POSIX 正則表示式引擎實現的。這導致與標準 SQL/JSON 行為存在各種細微差異,這些差異在 第 9.7.3.8 節中進行了分類。但是請注意,其中描述的標誌字母不相容性不適用於 SQL/JSON,因為它將 XQuery 標誌字母轉換為與 POSIX 引擎期望的匹配。

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

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

9.16.3. SQL/JSON 查詢函式 #

表 9.54 中描述的 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.54. 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,或值 UNKNOWN(實際上是 SQL NULL)。如果未指定 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 型別或評估 ON EMPTY 表示式(如果 path_expression 評估返回空集)時發生錯誤時的行為。

  • 對於 ON EMPTYON ERROR,指定 ERROR 將導致丟擲帶有適當訊息的錯誤。其他選項包括返回 SQL NULL、空陣列(EMPTY [ARRAY])、空物件(EMPTY OBJECT)或使用者指定的表示式(DEFAULT expression),該表示式可以強制轉換為 jsonb 或 RETURNING 中指定的型別。如果未指定 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 的結果。

  • 僅當期望提取的值是單個 SQL/JSON 標量項時才使用 JSON_VALUE();獲取多個值將被視為錯誤。如果您期望提取的值可能是物件或陣列,請改用 JSON_QUERY 函式。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 子句進行處理。

注意

JSON_VALUE()path_expression 返回 JSON null 時返回 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 [, ...] )

每個語法元素都將在下面更詳細地描述。

上下文項, 路徑表示式 [ AS json_path_name ] [ PASSING { AS 變數名 } [, ...]]

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

COLUMNS ( json_table_column [, ...] )

COLUMNS 子句定義了構造檢視的模式。在此子句中,您可以指定每個列都將填充一個 SQL/JSON 值,該值是透過將 JSON 路徑表示式應用於行模式後獲得的。json_table_column 具有以下變體

名稱 FOR ORDINALITY

新增一個序號列,提供從 1 開始的順序行編號。每個 NESTED PATH(參見下文)都會為其任何巢狀序號列獲取自己的計數器。

名稱 型別 [FORMAT JSON [ENCODING UTF8]] [ PATH 路徑表示式 ]

將透過對行模式應用 path_expression 獲得的 SQL/JSON 值在強制轉換為指定的 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 子句,則為後者。

名稱 型別 EXISTS [ PATH 路徑表示式 ]

將透過對行模式應用 path_expression 獲得的布林值在強制轉換為指定的 type 後插入到檢視的輸出行中。

該值對應於將 PATH 表示式應用於行模式是否產生任何值。

指定的 type 應該可以從 boolean 型別進行轉換。

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

注意

此子句在內部轉換為 JSON_EXISTS,並具有相同的語義。

NESTED [ PATH ] 路徑表示式 [ 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
     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 級別使用 FOR ORDINALITY 列(列 movie_idbook_idauthor_id

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)

提交更正

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