Sql 在表列上使用Postgres JSON函数

Sql 在表列上使用Postgres JSON函数,sql,json,postgresql,Sql,Json,Postgresql,我在Postgres文档和Google上进行了大量搜索,以查找表中实际JSON列上使用的JSON函数示例 这是我的问题:我试图使用jsonb_to_记录集从列中的JSON对象数组中提取键值,但得到语法错误。当我将对象逐字传递给函数时,它工作正常: 按字面意思传递JSON: select * from jsonb_to_recordset('[ { "id": 0, "name": "400MB-PDF.pdf", "extension": ".pdf", "trans

我在Postgres文档和Google上进行了大量搜索,以查找表中实际JSON列上使用的JSON函数示例

这是我的问题:我试图使用jsonb_to_记录集从列中的JSON对象数组中提取键值,但得到语法错误。当我将对象逐字传递给函数时,它工作正常:

按字面意思传递JSON:

select * 
from jsonb_to_recordset('[
    { "id": 0, "name": "400MB-PDF.pdf", "extension": ".pdf", 
        "transferId": "ap31fcoqcajjuqml6rng"}, 
    { "id": 0, "name": "1000MB-PDF.pdf", "extension": ".pdf", 
      "transferId": "ap31fcoqcajjuqml6rng"}
  ]') as f(name text);`
结果:

400MB-PDF.pdf
1000MB-PDF.pdf
它提取密钥名称的值

以下是列中的JSON,使用以下方法提取:

select journal.data::jsonb#>>'{context,data,files}' 
from journal 
where id = 'ap32bbofopvo7pjgo07g';
导致:

[ { "id": 0, "name": "400MB-PDF.pdf", "extension": ".pdf", 
    "transferId": "ap31fcoqcajjuqml6rng"}, 
  { "id": 0, "name": "1000MB-PDF.pdf", "extension": ".pdf", 
    "transferId": "ap31fcoqcajjuqml6rng"}
]
但是,当我尝试将jsonb>>“{context,data,files}”传递给jsonb_to_记录集时,如下所示:

select id, 
       journal.data::jsonb#>>::jsonb_to_recordset('{context,data,files}') as f(name text) 
from journal 
where id = 'ap32bbofopvo7pjgo07g';
我得到一个语法错误。我尝试了不同的方法,但每次它都抱怨语法错误:

版本: x86_64-unknown-linux-gnu上的PostgreSQL 9.4.10,由gcc Ubuntu 4.8.2-19ubuntu1 4.8.2编译,64位

选择后的表达式必须计算为单个值。因为jsonb_to_记录集返回一组行和列,所以不能在那里使用它

解决方案是横向交叉连接,它允许您使用函数将一行扩展为多行。这将为您提供选择可以操作的单行。例如:

select  *
from    journal j
cross join lateral
        jsonb_to_recordset(j.data#>'{context, data, files}') as d(id int, name text)
where   j.id = 'ap32bbofopvo7pjgo07g'
注意,返回类型text,>操作符返回类型jsonb。由于jsonb_to_记录集期望jsonb作为它的第一个参数,我正在使用>

jsonb_to_记录集是一个集值函数,只能在特定位置调用。FROM子句就是这样一个地方,这就是为什么第一个示例有效,而SELECT子句无效

为了将JSON数组转换为可以查询的表,需要使用横向联接。其效果相当于源记录集上的foreach循环,这就是应用jsonb_to_记录集函数的地方。以下是一个示例数据集:

create table jstuff (id int, val jsonb);

insert into jstuff
values
    (1, '[{"outer": {"inner": "a"}}, {"outer": {"inner": "b"}}]'),
    (2, '[{"outer": {"inner": "c"}}]');
一个简单的横向联接查询:

select id, r.*
from jstuff
join lateral jsonb_to_recordset(val) as r("outer" jsonb) on true;

 id |     outer      
----+----------------
  1 | {"inner": "a"}
  1 | {"inner": "b"}
  2 | {"inner": "c"}
(3 rows)
这是最难的部分。注意,您必须在AS子句中定义新记录集的外观-因为我们的val数组中的每个元素都是一个JSON对象,只有一个名为outer的字段,这就是我们给它的。如果数组元素包含您感兴趣的多个字段,则可以用类似的方式声明这些字段。还要注意,JSON模式需要一致:如果数组元素不包含名为outer的键,则结果值将为null

从这里开始,您只需要使用遍历操作符从每个JSON对象中提取所需的特定值。如果我只需要样本数据集中的内部值,我会指定select id,r.outer->>'inner'。因为它已经是JSONB了,所以不需要强制转换