使用json_populate_recordset从单个JSON对象填充多个表

时间:2014-11-20 15:35:23

标签: sql json postgresql import common-table-expression

我已阅读related question,但与用户kenthewala不同,我希望将JSON对象数组添加到数据库中。

我的JSON文件如下所示:

{
"tablename_a":[{"a_id":1,"b_id":2,"c_id":3},
 {"a_id":2,"b_id":51,"c_id":3}],
"tablename_b":[{"b_id":2,"name":"John Doe", "z_id":123},
 {"b_id":51,"name":"Mary Ann", "z_id":412}],
"tablename_c":[{"c_id":3, "OS type":"Windows 7"}],
"tablename_z":[{"z_id":123, "Whatever":"Something"},
{"z_id":123, "Whatever":"Something else"}]
}

db。中已存在具有相应名称的表。

在伪代码中我想象了类似

for each key in JSON_FILE as tbl_name
(
  insert into tbl_name select * from json_populate_recordset
  (
    null::tbl_name, 'content of tbl_name'
  )
)

但我不确定,如何实现这一点。

我正在使用PostgreSQL 9.3.5(如果有帮助的话,还有PHP 5.3.3)。

表结构类似于JSON文件(因为我最初从数据库导出JSON):

create table tablename_a (a_id integer, b_id integer, c_id integer);
create table tablename_b (b_id integer, name text, z_id integer);

等等。

1 个答案:

答案 0 :(得分:4)

3个步骤:

  1. 访问JSON对象的字段->
  2. 使用json_populate_recordset()从JSON记录数组创建派生表。
  3. 分解INSERT命令的行类型。
  4. 要重用所有表的输入值,请将其包装在data-modifying CTEs

    WITH input AS (
       SELECT '{
          "tablename_a":[{"a_id":1,"b_id":2,"c_id":3},
           {"a_id":2,"b_id":51,"c_id":3}],
          "tablename_b":[{"b_id":2,"name":"John Doe", "z_id":123},
           {"b_id":51,"name":"Mary Ann", "z_id":412}],
          "tablename_c":[{"c_id":3, "OS type":"Windows 7"}],
          "tablename_z":[{"z_id":123, "Whatever":"Something"},
          {"z_id":123, "Whatever":"Something else"}]
          }'::json AS j
       )
    ,  a AS (
       INSERT INTO tablename_a
       SELECT t.*
       FROM   input i
            , json_populate_recordset(NULL::tablename_a, i.j->'tablename_a') t
       )
    ,  b AS (
       INSERT INTO tablename_b
       SELECT t.*
       FROM   input i
            , json_populate_recordset(NULL::tablename_b, i.j->'tablename_b') t
       )
       -- ... more ...
    INSERT INTO tablename_z
    SELECT t.*
    FROM   input i
         , json_populate_recordset(NULL::tablename_z, i.j->'tablename_z') t
    ;
    

    <强> SQL Fiddle.

    使用隐式JOIN LATERAL。相关: