使用索引将多个数组的值插入表中

时间:2017-06-02 12:26:36

标签: json postgresql

续使用此post,创建一个函数来解析json输入,然后将值插入到三个表中,先前插入的id作为last的参数 插入

如果我想在同一个表中插入两个数组,我可以这样做

insert into t2 (car, car_type)
    select json_array_elements_text(d::json -> 'car'),json_array_elements_text(d::json -> 'car_type')::int4 returning id;
)

如何使其与索引一起使用,如下所示?

功能

create or replace function test_func(d json)
returns void as $$
  begin
with j as (select d)
, a as (
  select car,brand,type, t1.id oid 
  from j
  join json_array_elements_text(j.d->'cars') with ordinality t1(car,id) on true
  join json_array_elements_text(j.d->'brands') with ordinality t2(brand,id) 
on t1.id = t2.id
  join json_array_elements_text(j.d->'car_type') with ordinality t2(type,id) 
on t1.id = t2.id  // this line apparently doesnt work, t2 has been joined twice
)
, n as (
 insert into t1 (name) values (d::json -> 'name') returning id
), c as (
  insert into t2 (cars,car_type) select car,type from a order by oid returning id // needs to insert two columns here from two arrays
)
, ag as (
  select array_agg(c.id) cid from c
)
insert into t3 (id, name_id, cars_id, brand)
  select 1, n.id,cid[oid], brand
  from a 
  join n on true
  join ag on true
;
end;
$$ language plpgsql;

表格

CREATE TABLE t1 ( "id" SERIAL PRIMARY KEY, "name" text NOT NULL );
CREATE TABLE t2 ( "id" SERIAL PRIMARY KEY, "cars" text NOT NULL, "car_type" int );
CREATE TABLE t3 ( "id" int, "name_id" int REFERENCES t1(id), "cars_id" int REFERENCES t2(id), "brand" text );

测试

select test_func('{"name":"john", "cars":["bmw X5 xdrive","volvo v90 rdesign"], "brands":["bmw","volvo"],"car_type":[1,1]}');

1 个答案:

答案 0 :(得分:0)

您使用t2对两个不同的集进行别名 - 尝试:

create or replace function test_func(d json)
returns void as $$
  begin
with j as (select d)
, a as (
  select car,brand,car_type, t1.id oid 
  from j
  join json_array_elements_text(j.d->'cars') with ordinality t1(car,id) on true
  join json_array_elements_text(j.d->'brands') with ordinality t2(brand,id) 
on t1.id = t2.id
  join json_array_elements_text(j.d->'car_type') with ordinality car_t(car_type,id) 
on t1.id = car_t.id 
)
, n as (
 insert into t1 (name) values (d::json -> 'name') returning id
), c as (
  insert into t2 (cars,car_type) select car,car_type::int from a order by oid returning id -- needs to insert two columns here from two arrays
)
, ag as (
  select array_agg(c.id) cid from c
)
insert into t3 (id, name_id, cars_id, brand)
  select 1, n.id,cid[oid], brand
  from a 
  join n on true
  join ag on true
;
end;
$$ language plpgsql;

结果:

t=# select * from t2;
 id |       cars        | car_type
----+-------------------+----------
  1 | bmw X5 xdrive     |        1
  2 | volvo v90 rdesign |        1
(2 rows)