-- Should fail (JSON_TABLE can be used only in FROM clause) SELECT JSON_TABLE('[]', '$');
-- Only allow EMPTY and ERROR for ON ERROR SELECT * FROM JSON_TABLE('[]', 'strict $.a' COLUMNS (js2 int PATH '$') DEFAULT1ON ERROR); SELECT * FROM JSON_TABLE('[]', 'strict $.a' COLUMNS (js2 int PATH '$') NULLON ERROR); SELECT * FROM JSON_TABLE('[]', 'strict $.a' COLUMNS (js2 int PATH '$') EMPTY ON ERROR); SELECT * FROM JSON_TABLE('[]', 'strict $.a' COLUMNS (js2 int PATH '$') ERROR ON ERROR);
-- Column and path names must be distinct SELECT * FROM JSON_TABLE(jsonb'"1.23"', '$.a'as js2 COLUMNS (js2 int path '$'));
-- Should fail (no columns) SELECT * FROM JSON_TABLE(NULL, '$' COLUMNS ());
SELECT * FROM JSON_TABLE (NULL::jsonb, '$' COLUMNS (v1 timestamp)) AS f (v1, v2);
--duplicated column name SELECT * FROM JSON_TABLE(jsonb'"1.23"', '$.a' COLUMNS (js2 int path '$', js2 int path '$'));
--return composite data type. create type comp as (a int, b int); SELECT * FROM JSON_TABLE(jsonb '{"rec": "(1,2)"}', '$' COLUMNS (id FOR ORDINALITY, comp comp path '$.rec' omit quotes)) jt; drop type comp;
-- NULL => empty table SELECT * FROM JSON_TABLE(NULL::jsonb, '$' COLUMNS (foo int)) bar; SELECT * FROM JSON_TABLE(jsonb'"1.23"', 'strict $.a' COLUMNS (js2 int PATH '$'));
-- SELECT * FROM JSON_TABLE(jsonb '123', '$'
COLUMNS (item int PATH '$', foo int)) bar;
-- "formatted" columns SELECT * FROM json_table_test vals LEFTOUTERJOIN
JSON_TABLE(
vals.js::jsonb, 'lax $[*]'
COLUMNS (
id FOR ORDINALITY,
jst text FORMAT JSON PATH '$',
jsc char(4) FORMAT JSON PATH '$',
jsv varchar(4) FORMAT JSON PATH '$',
jsb jsonb FORMAT JSON PATH '$',
jsbq jsonb FORMAT JSON PATH '$' OMIT QUOTES
)
) jt ONtrue;
-- EXISTS columns SELECT * FROM json_table_test vals LEFTOUTERJOIN
JSON_TABLE(
vals.js::jsonb, 'lax $[*]'
COLUMNS (
id FOR ORDINALITY,
exists1 bool EXISTS PATH '$.aaa',
exists2 intEXISTS PATH '$.aaa',
exists3 intEXISTS PATH 'strict $.aaa' UNKNOWN ON ERROR,
exists4 text EXISTS PATH 'strict $.aaa'FALSEON ERROR
)
) jt ONtrue;
-- Other miscellaneous checks SELECT * FROM json_table_test vals LEFTOUTERJOIN
JSON_TABLE(
vals.js::jsonb, 'lax $[*]'
COLUMNS (
id FOR ORDINALITY,
aaa int, -- "aaa" has implicit path '$."aaa"'
aaa1 int PATH '$.aaa',
js2 json PATH '$',
jsb2w jsonb PATH '$'WITH WRAPPER,
jsb2q jsonb PATH '$' OMIT QUOTES,
ia int[] PATH '$',
ta text[] PATH '$',
jba jsonb[] PATH '$'
)
) jt ONtrue;
-- Test using casts in DEFAULT .. ON ERROR expression SELECT * FROM JSON_TABLE(jsonb '{"d1": "H"}', '$'
COLUMNS (js1 jsonb_test_domain PATH '$.a2'DEFAULT'"foo1"'::jsonb::text ON EMPTY));
SELECT * FROM JSON_TABLE(jsonb '{"d1": "H"}', '$'
COLUMNS (js1 jsonb_test_domain PATH '$.a2'DEFAULT'foo'::jsonb_test_domain ON EMPTY));
SELECT * FROM JSON_TABLE(jsonb '{"d1": "H"}', '$'
COLUMNS (js1 jsonb_test_domain PATH '$.a2'DEFAULT'foo1'::jsonb_test_domain ON EMPTY));
SELECT * FROM JSON_TABLE(jsonb '{"d1": "foo"}', '$'
COLUMNS (js1 jsonb_test_domain PATH '$.d1'DEFAULT'foo2'::jsonb_test_domain ON ERROR));
SELECT * FROM JSON_TABLE(jsonb '{"d1": "foo"}', '$'
COLUMNS (js1 oid[] PATH '$.d2'DEFAULT'{1}'::int[]::oid[] ON EMPTY));
EXPLAIN (COSTS OFF, VERBOSE) SELECT * FROM jsonb_table_view2; EXPLAIN (COSTS OFF, VERBOSE) SELECT * FROM jsonb_table_view3; EXPLAIN (COSTS OFF, VERBOSE) SELECT * FROM jsonb_table_view4; EXPLAIN (COSTS OFF, VERBOSE) SELECT * FROM jsonb_table_view5; EXPLAIN (COSTS OFF, VERBOSE) SELECT * FROM jsonb_table_view6;
-- JSON_TABLE() with alias EXPLAIN (COSTS OFF, VERBOSE) SELECT * FROM
JSON_TABLE(
jsonb 'null', 'lax $[*]' PASSING 1 + 2AS a, json '"foo"'AS"b c"
COLUMNS (
id FOR ORDINALITY, "int"int PATH '$', "text" text PATH '$'
)) json_table_func;
EXPLAIN (COSTS OFF, FORMAT JSON, VERBOSE) SELECT * FROM
JSON_TABLE(
jsonb 'null', 'lax $[*]' PASSING 1 + 2AS a, json '"foo"'AS"b c"
COLUMNS (
id FOR ORDINALITY, "int"int PATH '$', "text" text PATH '$'
)) json_table_func;
DROP VIEW jsonb_table_view2; DROP VIEW jsonb_table_view3; DROP VIEW jsonb_table_view4; DROP VIEW jsonb_table_view5; DROP VIEW jsonb_table_view6; DROP DOMAIN jsonb_test_domain;
-- JSON_TABLE: only one FOR ORDINALITY columns allowed SELECT * FROM JSON_TABLE(jsonb '1', '$' COLUMNS (id FOR ORDINALITY, id2 FOR ORDINALITY, a int PATH '$.a' ERROR ON EMPTY)) jt; SELECT * FROM JSON_TABLE(jsonb '1', '$' COLUMNS (id FOR ORDINALITY, a int PATH '$' ERROR ON EMPTY)) jt;
-- JSON_TABLE: ON EMPTY/ON ERROR behavior SELECT * FROM
(VALUES ('1'), ('"err"')) vals(js),
JSON_TABLE(vals.js::jsonb, '$' COLUMNS (a int PATH '$')) jt;
SELECT * FROM
(VALUES ('1'), ('"err"')) vals(js) LEFTOUTERJOIN
JSON_TABLE(vals.js::jsonb, '$' COLUMNS (a int PATH '$' ERROR ON ERROR)) jt ONtrue;
-- TABLE-level ERROR ON ERROR is not propagated to columns SELECT * FROM
(VALUES ('1'), ('"err"')) vals(js) LEFTOUTERJOIN
JSON_TABLE(vals.js::jsonb, '$' COLUMNS (a int PATH '$' ERROR ON ERROR)) jt ONtrue;
SELECT * FROM JSON_TABLE(jsonb '1', '$' COLUMNS (a int PATH '$.a' ERROR ON EMPTY)) jt; SELECT * FROM JSON_TABLE(jsonb '1', '$' COLUMNS (a int PATH 'strict $.a' ERROR ON ERROR) ERROR ON ERROR) jt; SELECT * FROM JSON_TABLE(jsonb '1', '$' COLUMNS (a int PATH 'lax $.a' ERROR ON EMPTY) ERROR ON ERROR) jt;
SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int PATH '$'DEFAULT1ON EMPTY DEFAULT2ONERROR)) jt; SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int PATH 'strict $.a'DEFAULT1ON EMPTY DEFAULT2ON ERROR)) jt; SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int PATH 'lax $.a'DEFAULT1ON EMPTY DEFAULT2ON ERROR)) jt;
-- JSON_TABLE: EXISTS PATH types SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int4EXISTS PATH '$.a' ERROR ON ERROR)); -- ok; can cast to int4 SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int4EXISTS PATH '$' ERROR ON ERROR)); -- ok; can cast to int4 SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int2EXISTS PATH '$.a')); SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int8EXISTS PATH '$.a')); SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a float4EXISTS PATH '$.a')); -- Default FALSE (ON ERROR) doesn't fit char(3) SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a char(3) EXISTS PATH '$.a')); SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a char(3) EXISTS PATH '$.a' ERROR ON ERROR)); SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a char(5) EXISTS PATH '$.a' ERROR ON ERROR)); SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a json EXISTS PATH '$.a')); SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a jsonb EXISTS PATH '$.a'));
-- EXISTS PATH domain over int CREATE DOMAIN dint4 ASint; CREATE DOMAIN dint4_0 ASintCHECK (VALUE <> 0 ); SELECT a, a::bool FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a dint4 EXISTS PATH '$.a' )); SELECT a, a::bool FROM JSON_TABLE(jsonb '{"a":1}', '$' COLUMNS (a dint4_0 EXISTS PATH '$.b')); SELECT a, a::bool FROM JSON_TABLE(jsonb '{"a":1}', '$' COLUMNS (a dint4_0 EXISTS PATH '$.b' ERROR ON ERROR)); SELECT a, a::bool FROM JSON_TABLE(jsonb '{"a":1}', '$' COLUMNS (a dint4_0 EXISTS PATH '$.b'FALSEON ERROR)); SELECT a, a::bool FROM JSON_TABLE(jsonb '{"a":1}', '$' COLUMNS (a dint4_0 EXISTS PATH '$.b'TRUEON ERROR)); DROP DOMAIN dint4, dint4_0;
-- JSON_TABLE: WRAPPER/QUOTES clauses on scalar columns SELECT * FROM JSON_TABLE(jsonb '"world"', '$' COLUMNS (item text PATH '$' KEEP QUOTES ON SCALAR STRING)); SELECT * FROM JSON_TABLE(jsonb '"world"', '$' COLUMNS (item text PATH '$' OMIT QUOTES ON SCALAR STRING)); SELECT * FROM JSON_TABLE(jsonb '"world"', '$' COLUMNS (item text FORMAT JSON PATH '$' KEEP QUOTES)); SELECT * FROM JSON_TABLE(jsonb '"world"', '$' COLUMNS (item text FORMAT JSON PATH '$' OMIT QUOTES)); SELECT * FROM JSON_TABLE(jsonb '"world"', '$' COLUMNS (item text FORMAT JSON PATH '$' WITHOUT WRAPPER KEEP QUOTES)); SELECT * FROM JSON_TABLE(jsonb '"world"', '$' COLUMNS (item text PATH '$' WITHOUT WRAPPER OMIT QUOTES));
SELECT * FROM JSON_TABLE(jsonb '"world"', '$' COLUMNS (item text FORMAT JSON PATH '$'WITH WRAPPER));
-- Error: OMIT QUOTES should not be specified when WITH WRAPPER is present SELECT * FROM JSON_TABLE(jsonb '"world"', '$' COLUMNS (item text PATH '$'WITH WRAPPER OMIT QUOTES)); -- But KEEP QUOTES (the default) is fine SELECT * FROM JSON_TABLE(jsonb '"world"', '$' COLUMNS (item text FORMAT JSON PATH '$'WITH WRAPPER KEEP QUOTES));
-- Test PASSING args SELECT * FROM JSON_TABLE(
jsonb '[1,2,3]', '$[*] ? (@ < $x)'
PASSING 3AS x
COLUMNS (y text FORMAT JSON PATH '$')
) jt;
-- PASSING arguments are also passed to column paths SELECT * FROM JSON_TABLE(
jsonb '[1,2,3]', '$[*] ? (@ < $x)'
PASSING 10AS x, 3AS y
COLUMNS (a text FORMAT JSON PATH '$ ? (@ < $y)')
) jt;
-- Should fail (not supported) SELECT * FROM JSON_TABLE(jsonb '{"a": 123}', '$' || '.' || 'a' COLUMNS (foo int));
-- JsonPathQuery() error message mentioning column name SELECT * FROM JSON_TABLE('{"a": [{"b": "1"}, {"b": "2"}]}', '$' COLUMNS (b json path '$.a[*].b' ERROR ON ERROR));
-- JSON_TABLE: nested paths
-- Duplicate path names SELECT * FROM JSON_TABLE(
jsonb '[]', '$'AS a
COLUMNS (
b int,
NESTED PATH '$'AS a
COLUMNS (
c int
)
)
) jt;
SELECT * FROM JSON_TABLE(
jsonb '[]', '$'AS a
COLUMNS (
b int,
NESTED PATH '$'AS n_a
COLUMNS (
c int
)
)
) jt;
SELECT * FROM JSON_TABLE(
jsonb '[]', '$'
COLUMNS (
b int,
NESTED PATH '$'AS b
COLUMNS (
c int
)
)
) jt;
SELECT * FROM JSON_TABLE(
jsonb '[]', '$'
COLUMNS (
NESTED PATH '$'AS a
COLUMNS (
b int
),
NESTED PATH '$'
COLUMNS (
NESTED PATH '$'AS a
COLUMNS (
c int
)
)
)
) jt;
select
jt.* from
jsonb_table_test jtt,
json_table (
jtt.js,'strict $[*]'as p
columns (
n for ordinality,
a int path 'lax $.a'default -1on empty,
nested path 'strict $.b[*]'as pb columns (b_id for ordinality, b int path '$' ),
nested path 'strict $.c[*]'as pc columns (c_id for ordinality, c int path '$' )
)
) jt;
-- PASSING arguments are passed to nested paths and their columns' paths SELECT * FROM
generate_series(1, 3) x,
generate_series(1, 3) y,
JSON_TABLE(jsonb '[[1,2,3],[2,3,4,5],[3,4,5,6]]', 'strict $[*] ? (@[*] <= $x)'
PASSING x AS x, y AS y
COLUMNS (
y text FORMAT JSON PATH '$',
NESTED PATH 'strict $[*] ? (@ == $y)'
COLUMNS (
z int PATH '$'
)
)
) jt;
-- JSON_TABLE: Test backward parsing with nested paths
CREATE VIEW jsonb_table_view_nested AS SELECT * FROM
JSON_TABLE(
jsonb 'null', 'lax $[*]' PASSING 1 + 2AS a, json '"foo"'AS"b c"
COLUMNS (
id FOR ORDINALITY,
NESTED PATH '$[1]'AS p1 COLUMNS (
a1 int,
NESTED PATH '$[*]'AS"p1 1" COLUMNS (
a11 text
),
b1 text
),
NESTED PATH '$[2]'AS p2 COLUMNS (
NESTED PATH '$[*]'AS"p2:1" COLUMNS (
a21 text
),
NESTED PATH '$[*]'AS p22 COLUMNS (
a22 text
)
)
)
);
\sv jsonb_table_view_nested DROP VIEW jsonb_table_view_nested;
CREATETABLE s (js jsonb); INSERTINTO s VALUES
('{"a":{"za":[{"z1": [11,2222]},{"z21": [22, 234,2345]},{"z22": [32, 204,145]}]},"c": 3}'),
('{"a":{"za":[{"z1": [21,4222]},{"z21": [32, 134,1345]}]},"c": 10}');
-- error SELECT sub.* FROM s,
JSON_TABLE(js, '$' PASSING 32AS x, 13AS y COLUMNS (
xx int path '$.c',
NESTED PATH '$.a.za[1]' columns (NESTED PATH '$.z21[*]' COLUMNS (z21 int path '$?(@ >= $"x")' ERROR ON ERROR))
)) sub;
-- Parent columns xx1, xx appear before NESTED ones SELECT sub.* FROM s,
(VALUES (23)) x(x), generate_series(13, 13) y,
JSON_TABLE(js, '$'AS c1 PASSING x AS x, y AS y COLUMNS (
NESTED PATH '$.a.za[2]' COLUMNS (
NESTED PATH '$.z22[*]'as z22 COLUMNS (c int PATH '$')),
NESTED PATH '$.a.za[1]' columns (d int[] PATH '$.z21'),
NESTED PATH '$.a.za[0]' columns (NESTED PATH '$.z1[*]'as z1 COLUMNS (a int PATH '$')),
xx1 int PATH '$.c',
NESTED PATH '$.a.za[1]' columns (NESTED PATH '$.z21[*]'as z21 COLUMNS (b int PATH '$')),
xx int PATH '$.c'
)) sub;
-- Test applying PASSING variables at different nesting levels SELECT sub.* FROM s,
(VALUES (23)) x(x), generate_series(13, 13) y,
JSON_TABLE(js, '$'AS c1 PASSING x AS x, y AS y COLUMNS (
xx1 int PATH '$.c',
NESTED PATH '$.a.za[0].z1[*]' COLUMNS (NESTED PATH '$ ?(@ >= ($"x" -2))' COLUMNS (a int PATH '$')),
NESTED PATH '$.a.za[0]' COLUMNS (NESTED PATH '$.z1[*] ? (@ >= ($"x" -2))' COLUMNS (b int PATH '$'))
)) sub;
-- Test applying PASSING variable to paths all the levels SELECT sub.* FROM s,
(VALUES (23)) x(x),
generate_series(13, 13) y,
JSON_TABLE(js, '$'AS c1 PASSING x AS x, y AS y
COLUMNS (
xx1 int PATH '$.c',
NESTED PATH '$.a.za[1]'
COLUMNS (NESTED PATH '$.z21[*]' COLUMNS (b int PATH '$')),
NESTED PATH '$.a.za[1] ? (@.z21[*] >= ($"x"-1))' COLUMNS
(NESTED PATH '$.z21[*] ? (@ >= ($"y" + 3))'as z22 COLUMNS (a int PATH '$ ? (@ >= ($"y" + 12))')),
NESTED PATH '$.a.za[1]' COLUMNS
(NESTED PATH '$.z21[*] ? (@ >= ($"y" +121))'as z21 COLUMNS (c int PATH '$ ? (@ > ($"x" +111))'))
)) sub;
----- test on empty behavior SELECT sub.* FROM s,
(values(23)) x(x),
generate_series(13, 13) y,
JSON_TABLE(js, '$'AS c1 PASSING x AS x, y AS y
COLUMNS (
xx1 int PATH '$.c',
NESTED PATH '$.a.za[2]' COLUMNS (NESTED PATH '$.z22[*]'as z22 COLUMNS (c int PATH '$')),
NESTED PATH '$.a.za[1]' COLUMNS (d json PATH '$ ? (@.z21[*] == ($"x" -1))'),
NESTED PATH '$.a.za[0]' COLUMNS (NESTED PATH '$.z1[*] ? (@ >= ($"x" -2))'as z1 COLUMNS (a int PATH '$')),
NESTED PATH '$.a.za[1]' COLUMNS
(NESTED PATH '$.z21[*] ? (@ >= ($"y" +121))'as z21 COLUMNS (b int PATH '$ ? (@ > ($"x" +111))'DEFAULT0ON EMPTY))
)) sub;
CREATEORREPLACE VIEW jsonb_table_view7 AS SELECT sub.* FROM s,
(values(23)) x(x),
generate_series(13, 13) y,
JSON_TABLE(js, '$'AS c1 PASSING x AS x, y AS y
COLUMNS (
xx1 int PATH '$.c',
NESTED PATH '$.a.za[2]' COLUMNS (NESTED PATH '$.z22[*]'as z22 COLUMNS (c int PATH '$' WITHOUT WRAPPER OMIT QUOTES)),
NESTED PATH '$.a.za[1]' COLUMNS (d json PATH '$ ? (@.z21[*] == ($"x" -1))'WITH WRAPPER),
NESTED PATH '$.a.za[0]' COLUMNS (NESTED PATH '$.z1[*] ? (@ >= ($"x" -2))'as z1 COLUMNS (a int PATH '$' KEEP QUOTES)),
NESTED PATH '$.a.za[1]' COLUMNS
(NESTED PATH '$.z21[*] ? (@ >= ($"y" +121))'as z21 COLUMNS (b int PATH '$ ? (@ > ($"x" +111))'DEFAULT0ON EMPTY))
)) sub;
\sv jsonb_table_view7 DROP VIEW jsonb_table_view7; DROPTABLE s;
-- Prevent ON EMPTY specification on EXISTS columns SELECT * FROM JSON_TABLE(jsonb '1', '$' COLUMNS (a intexists empty object on empty));
-- Test ON ERROR / EMPTY value validity for the function and column types; -- all fail SELECT * FROM JSON_TABLE(jsonb '1', '$' COLUMNS (a int) NULLON ERROR); SELECT * FROM JSON_TABLE(jsonb '1', '$' COLUMNS (a inttrueon empty)); SELECT * FROM JSON_TABLE(jsonb '1', '$' COLUMNS (a int omit quotes trueon error)); SELECT * FROM JSON_TABLE(jsonb '1', '$' COLUMNS (a intexists empty object on error));
-- Test JSON_TABLE() column deparsing -- don't emit default ON ERROR / EMPTY -- behavior CREATE VIEW json_table_view8 ASSELECT * from JSON_TABLE('"a"', '$' COLUMNS (a text PATH '$'));
\sv json_table_view8;
CREATE VIEW json_table_view9 ASSELECT * from JSON_TABLE('"a"', '$' COLUMNS (a text PATH '$') ERROR ON ERROR);
\sv json_table_view9;
DROP VIEW json_table_view8, json_table_view9;
-- Test JSON_TABLE() deparsing -- don't emit default ON ERROR behavior CREATE VIEW json_table_view8 ASSELECT * from JSON_TABLE('"a"', '$' COLUMNS (a text PATH '$') EMPTY ON ERROR);
\sv json_table_view8;
CREATE VIEW json_table_view9 ASSELECT * from JSON_TABLE('"a"', '$' COLUMNS (a text PATH '$') EMPTY ARRAY ON ERROR);
\sv json_table_view9;
DROP VIEW json_table_view8, json_table_view9;
Messung V0.5 in Prozent
[Konzepte0.24Was zu einem Entwurf gehörtWie die Entwicklung von Software durchgeführt wird2026-08-08]