我在 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)
);
有时在表中嵌套结构是合理的,但在这些情况下使用 jsonb
或 hstore
似乎更方便和自然,例如:
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/