sql - 扩展存储在 JSONB 中的对象数组

标签 sql arrays json postgresql jsonb

我有一个表,其中包含一个 JSONB 字段,其中包含一个格式简单的 JSON 数组,我想对其进行扩展。这是该表定义的精简版本:

CREATE TABLE IF NOT EXISTS data.data_file_info (
    id uuid NOT NULL,
    server_name_ citext NOT NULL,
    table_stats jsonb DEFAULT '{}'::jsonb NOT NULL,
    PRIMARY KEY(id)
);

以下是 table_stats JSONB 字段中的一些示例数据:

[
    {"table_name":"AutoReportOrg","record_count":48,"table_number":167},
    {"table_name":"AutoReportOrgAudit","record_count":0,"table_number":170},
    {"table_name":"AutoReportOrgRecipient","record_count":126,"table_number":168},
    {"table_name":"AutoReportRecipient","record_count":28,"table_number":169}
]

json_populate_recordset和/或 json_to_recordset功能看起来应该是我所追求的,但我一直无法让它们工作。我查看了很多过去的问题,并尝试了各种语法。以下是我的印象应该有效...但事实并非如此:

-- Define a custom type to act as a template for the JSON parser.
DROP TYPE IF EXISTS dfits;
CREATE TYPE api.dfits AS (
    table_name citext,
    record_count int8,
    table_number int4);

-- And now we parse!
SELECT server_name_, (json_populate_recordset(null::dfits, table_stats)).* FROM data_file_info;

但是我得到了这个:

ERROR:  function json_populate_recordset(dfits, jsonb) does not exist
LINE 4: SELECT server_name_, (json_populate_recordset(null::dfits, t...
                              ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts. (Line 9)

有人能发现我的设置中的错误吗?看起来我已经找到了正确的部分,但我无法将它们正确地组合在一起。

Postgres 11.4,部署在 RDS 上。

跟进

GMB 回答了我的问题,但我想在此处添加更多内容以供存档。过去我的打字错误(JSON 而不是 JSONB),这个问题的关键似乎是 Postgres 需要一个模板/映射来定义 JSON/JSONB 数组中元素的结构。我认为在这种情况下,可以从四个(?)地方输入数据:

  • 现有的表定义,因为每个表都是一种类型。
  • 现有 View 定义,因为每个 View 都是一种类型。 (您可以在 pg_class 中找到它们以及基表派生类型。
  • 使用 CREATE TYPE 创建的自定义类型,就像我上面使用的那样。
  • 内嵌声明。

为了进行比较,下面是使用上面显示的自定义类型 dfits 的更新查询:

SELECT server_name_, expanded_json.*
FROM
   data_file_info, 
   jsonb_populate_recordset(null::dfits, table_stats) as expanded_json

现在这是使用内联声明的另一个版本:

SELECT server_name_, expanded_json.*
FROM
   data_file_info, 
    jsonb_to_recordset(table_stats) as expanded_json 
        (table_name text, record_count int, table_number int)

我可以看到这两种方法的用途。但是,话虽如此,CREATE TYPE 非常棒。您可以将其与 CREATE CAST 结合起来,形成非常紧凑且易于使用的代码。

最佳答案

由于您使用的是 jsonb 列,因此您实际上需要 jsonb_populate_recordset。另外,该函数返回一组记录,因此需要将其放在 FROM 子句中,而不是放在 SELECT 子句中。

考虑:

SELECT server_name, x.*
FROM
   data_file_info, 
   jsonb_populate_recordset(null::dfits, table_stats) x

<强> Demo on DB Fiddle :

| server_name | table_name             | record_count | table_number |
| ----------- | ---------------------- | ------------ | ------------ |
| foo         | AutoReportOrg          | 48           | 167          |
| foo         | AutoReportOrgAudit     | 0            | 170          |
| foo         | AutoReportOrgRecipient | 126          | 168          |
| foo         | AutoReportRecipient    | 28           | 169          |

关于sql - 扩展存储在 JSONB 中的对象数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58243737/

相关文章:

sql - 提高 Sql Delete 的性能

python - 如何根据条件有效地将函数应用于数组中的值?

c++ - 将字符串添加到 2d 数组并显示 cout 消息时出错(没有错误消息?)

MySQL SELECT table.column AS 表

sql - Grails - 存储将由服务使用的 sql

mysql - SQL 选择过去 45 天的所有数据

arrays - 在 Swift 中将数组变量转换为数据

json - 在推送到 ko.observableArray 之前格式化 JSON 日期

ios - AFNetworking 和 id reponseObject 不工作并且无法恢复内容

c# - 是微软的 Json (System.Runtime.Serialization.Json) 错误吗?