json - 将 json 转换为嵌套的 postgres 复合类型

标签 json postgresql composite-types

我在 postgres 中定义了以下嵌套类型:

CREATE TYPE address AS (
  name    text,
  street  text,
  zip     text,
  city    text,
  country text
);

CREATE TYPE customer AS (
  customer_number           text,
  created                   timestamp WITH TIME ZONE,
  default_billing_address   address,
  default_shipping_address  address
);

现在想在存储过程中填充此类型,该存储过程将 json 作为输入参数。这适用于顶级字段,输出显示了 postgres 复合类型的内部格式:

# select json_populate_record(null::customer, '{"customer_number":"12345678"}'::json)::customer;
 json_populate_record 
----------------------
 (12345678,,,)
(1 row)

但是,postgres 不处理嵌套的 json 结构:

# select json_populate_record(null::customer, '{"customer_number":"12345678","default_shipping_address":{"name":"","street":"","zip":"12345","city":"Berlin","country":"DE"}}'::json)::customer;
ERROR:  malformed record literal: "{"name":"","street":"","zip":"12345","city":"Berlin","country":"DE"}"
DETAIL:  Missing left parenthesis.

再次起作用的是,如果嵌套属性是 postgres 的内部格式,如下所示:

# select json_populate_record(null::customer, '{"customer_number":"12345678","default_shipping_address":"(\"\",\"\",12345,Berlin,DE)"}'::json)::customer;
            json_populate_record            
--------------------------------------------
 (12345678,,,"("""","""",12345,Berlin,DE)")
(1 row)

有什么方法可以让postgres从嵌套的json结构转换成相应的复合类型?

最佳答案

仅对嵌套对象使用 json_populate_record():

with a_table(jdata) as (
values
    ('{
        "customer_number":"12345678",
        "default_shipping_address":{
            "name":"",
            "street":"",
            "zip":"12345",
            "city":"Berlin",
            "country":"DE"
        }
    }'::json)
)
select (
    jdata->>'customer_number', 
    jdata->>'created', 
    json_populate_record(null::address, jdata->'default_billing_address'),
    json_populate_record(null::address, jdata->'default_shipping_address')
    )::customer
from a_table;

                    row                     
--------------------------------------------
 (12345678,,,"("""","""",12345,Berlin,DE)")
(1 row) 

嵌套复合类型不是 Postgres(和任何 RDBMS)的设计目标。它们太复杂和麻烦了。 在数据库逻辑中,嵌套结构应作为相关表进行维护,例如

create table addresses (
    address_id serial primary key,
    name text,
    street text,
    zip text,
    city text,
    country text
);

create table customers (
    customer_id serial primary key, -- not necessary `serial` may be `integer` or `bigint`
    customer_number text,           -- maybe redundant
    created timestamp with time zone,
    default_billing_address int references adresses(address_id),
    default_shipping_address int references adresses(address_id)
);

有时在表中嵌套结构是合理的,但在这些情况下使用 jsonbhstore 似乎更方便和自然,例如:

create table customers (
    customer_id serial primary key, 
    customer_number text,
    created timestamp with time zone,
    default_billing_address jsonb,
    default_shipping_address jsonb
);

关于json - 将 json 转换为嵌套的 postgres 复合类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40047868/

相关文章:

javascript - 获取 http.get 数据到本地 JSON 数组变量

php - 以编程方式向 JSON 添加数据的最简单方法是什么?

php - groupBy([]) 不工作

sql - 存储过程/存储函数 : SELECT in PostgreSQL

java - Gradle 依赖声明(JSR310),但 LocalDateTimeDeserializer 不可导入

Python 在加载修改后的 json 时抛出错误

python - 将 ascii 文本文件的一部分上传到 PostgreSQL 表中

database - PostgreSQL 在 Ubuntu 14.04 上安装失败

java - 如何使用 Hibernate 映射用户数据类型(复合类型)

sql - 列表理解与 PostgreSQL 数组