postgresql - 在 11.7 上解压缩 JSONB 数据并将其用作 PL/PgSQL 函数
问题描述
我正在开发一个函数,该函数采用一对 JSON 数组和一些设置值,然后在数组中的项目之间进行比较。在此之前,我试图在 PG/PlSQL 中解析 JSONB。这个在函数体中带有硬编码 JSON 的版本可以工作:
CREATE OR REPLACE FUNCTION tools.try_unpacking_hard_coded (
base_jsonb_in jsonb)
RETURNS TABLE (
base_text citext,
base_id citext)
AS $BODY$
BEGIN
RETURN QUERY
with
base_expanded AS (
select *
from json_populate_recordset(
null::record,
'[
{"base_text":"Red Large Special","base_id":1},
{"base_text":"Blue Small","base_id":5},
{"base_text":"Green Medium Special","base_id":87}
]')
AS unpacked (base_text citext, base_id citext)
)
select base_expanded.base_text,
base_expanded.base_id
from base_expanded;
END
$BODY$
LANGUAGE plpgsql;
这是一个示例调用和输出:
select * from try_unpacking_hard_coded('{}'::jsonb);
base_text base_id
Red Large Special 1
Blue Small 5
Green Medium Special 87
但是,当我尝试传入 JSON 文本并将其解析为参数时,我只得到NULL
结果。我得到了正确的名称和列数,以及正确的行数……但没有值。
CREATE OR REPLACE FUNCTION tools.try_unpacking (
base_jsonb_in jsonb)
RETURNS TABLE (
base_text citext,
base_id citext)
AS $BODY$
BEGIN
RETURN QUERY
WITH
base_expanded AS (
select *
from jsonb_populate_recordset(
null::record,
base_jsonb_in)
AS base_unpacked (base_text citext, base_id citext)
)
select base_expanded.base_text,
base_expanded.base_id
from base_expanded;
END
$BODY$
LANGUAGE plpgsql;
这是电话:
select * from try_unpacking (
'[{"text":"Red Large Special","id":"1"},
{"text":"Blue Small","id":"5"},
{"text":"Green Medium Special","id":"87"}]'
);
结果:
base_text base_id
NULL NULL
NULL NULL
NULL NULL
有人可以指出我正确的方向来解决这个问题吗?
跟进
Barbaros Özhan 好心指出我的错误,这是一个工作版本:
CREATE OR REPLACE FUNCTION tools.try_unpacking (
base_jsonb_in jsonb)
RETURNS TABLE (
base_text citext,
base_id citext)
AS $BODY$
BEGIN
RETURN QUERY
WITH
base_expanded AS (
select *
from jsonb_populate_recordset(
null::record,
base_jsonb_in)
AS base_unpacked (text citext, id citext)
)
select base_expanded.text AS base_text,
base_expanded.id AS base_id
from base_expanded;
END
$BODY$
LANGUAGE plpgsql;
顺便说一句,重命名的原因是我接下来将有第二个带comparison
值的参数。
解决方案
作为函数参数的 JSON 值的键值应符合从jsonb_populate_recordset()
函数返回的各个列的定义的单独别名:
CREATE OR REPLACE FUNCTION try_unpacking (
base_jsonb_in jsonb)
RETURNS TABLE (
base_text varchar(100),
base_id varchar(100))
AS $BODY$
BEGIN
RETURN QUERY
WITH
base_expanded AS (
select *
from jsonb_populate_recordset(
null::record,
base_jsonb_in)
AS base_unpacked (bt varchar(100), bi varchar(100))
)
select b.bt, b.bi
from base_expanded b;
END
$BODY$
LANGUAGE plpgsql;
select * from try_unpacking (
'[{"bt":"Red Large Special","bi":"1"},
{"bt":"Blue Small","bi":"5"},
{"bt":"Green Medium Special","bi":"87"}]'
);
base_text base_id
Red Large Special 1
Blue Small 5
Green Medium Special 87
请注意,返回记录的列标题仍保留base_text
为base_id
RETURNS TABLE (
base_text varchar(100),
base_id varchar(100)
)
部分。
推荐阅读
- java - 通过 java 客户端动态添加文件从 S3 位置读取
- python - Python 后端 - 使用客户端证书保护 REST API
- python - Python如何旋转这个表
- flutter - 我可以在使用 setState 时制作模块化的小部件类吗?
- ansible - 在 ansible 中为特定任务使用密钥文件
- python - 如何在 mac Mojave 中安装 pycaret python 库
- amazon-web-services - 有没有办法通过 Terraform 按计划将代码从 AWS CodeCommit 提取到 EC2 实例?
- python - 在 Django 中更改日期格式
- r - ggplot:一些 Unicode 形状可以工作,而另一些则不能
- python - 使用 Auto_Arima 更好地拟合测试数据