将 JSON 数组插入 Postgres 表

uns*_*age 4 postgresql database-design stored-procedures

第1部分:

我正在使用 Postgres 9.5,我试图弄清楚如何使用 JSON 数组插入 postgres 表。我用以下命令创建了一个表:

CREATE TABLE inputtable (
data_point_id SERIAL PRIMARY KEY NOT NULL,
chart_id INTEGER NOT NULL,
user_id INTEGER NOT NULL,
properties jsonb NOT NULL
);
Run Code Online (Sandbox Code Playgroud)

json 数据格式如下所示:

[
    { col1: a, col2: 5, col3: 1, col4: one},
    { col1: b, col2: 6, col3: 2, col4: two},
    { col1: c, col2: 7, col3: 3, col4: three}
]
Run Code Online (Sandbox Code Playgroud)

由于一些变化,我现在必须能够基于 user_id 每行插入一个 json 对象。最后,我希望输出如下所示:

data_point_id  | chart_id | user_id |  properties
---------------+----------+----------+--------------
    1          |    1     |     1    | { "col1": "a", "col2": 1, "col3": 1, "col4": "one"}
    2          |    1     |     1    | { "col1": "b", "col2": 2, "col3": 2, "col4": "two"}
    3          |    1     |     1    | { "col1": "c", "col2": 3, "col3": 3, "col4": "three"}
Run Code Online (Sandbox Code Playgroud)

我尝试使用 unnest 将数据插入表中,其中:

INSERT INTO inputtable (user_id, chart_id, properties) 
    SELECT (1, 1, unnest('{ "col1": "a", "col2": 1, "col3": 1, "col4": "one"},{ "col1": "b", "col2": 2, "col3": 2, "col4": "two"},{ "col1": "c", "col2": 3, "col3": 3, "col4": "three"}')::json)
Run Code Online (Sandbox Code Playgroud)

但我收到关于 type 的错误ERROR: could not determine polymorphic type because input has type "unknown"

第2部分:

我也想知道如何更新这样的表。例如,我以 JSON 格式更改数据点,并希望更改属性,并且我期望输出:

data_point_id  | chart_id | user_id  |  properties
---------------+----------+----------+--------------
    1          |    1     |     1    | { "col1": "a", "col2": 6, "col3": 7, "col4": "eight"}
    2          |    1     |     1    | { "col1": "b", "col2": 10, "col3": 11, "col4": "twelve"}
    3          |    1     |     1    | { "col1": "c", "col2": 3, "col3": 3, "col4": "new"} 
Run Code Online (Sandbox Code Playgroud)

像这样使用数据:

[
    { col1: a, col2: 6, col3: 7, col4: eight},
    { col1: b, col2: 10, col3: 11, col4: twelve},
    { col1: c, col2: 3, col3: 3, col4: new}
]
Run Code Online (Sandbox Code Playgroud)

如何做到这一点?我认为第 2 部分的问题可以通过 jsonb_populate_recordset 解决,但我不确定。对 JSON 使用 Postgres 对我来说是新的,但它看起来非常强大,我感谢帮助我解决这个问题的帮助!

pie*_*rop 5

第 1 部分 - 插入

您不必使用unnest()butjsonb_array_elements()并将方括号添加到 JSON 数据结构中。我sugget你使用JSON验证网站像JSONlint来测试你的JSON数据的正确性。

此代码在 中插入 3 个新记录inputtable

WITH json_array AS (
    SELECT 1 AS user_id, 
           2 AS chart_id,
           jsonb_array_elements('
               [
                 {
                    "col1": "a",
                    "col2": 1,
                    "col3": 1,
                    "col4": "one"
                 }, {
                    "col1": "b",
                    "col2": 2,
                    "col3": 2,
                    "col4": "two"
                 }, {
                    "col1": "c",
                    "col2": 3,
                    "col3": 3,
                    "col4": "three"
                }
               ]'::jsonb) AS properties
)
INSERT INTO inputtable (user_id, chart_id, properties) 
SELECT * FROM json_array
Run Code Online (Sandbox Code Playgroud)

第 2 部分 - 更新

为了更新,您必须指定data_point_id值,因此您必须先验地知道它们。

这很完美,但可能还有其他幼稚的解决方案:

WITH update_table AS(
   SELECT unnest(ARRAY[1, 2, 3]) AS data_point_id,
          jsonb_array_elements('
            [
              {
                "col1": "a",
                "col2": 6,
                "col3": 7,
                "col4": "eight"
              }, {
                "col1": "b",
                "col2": 10,
                "col3": 11,
                "col4": "twelve"
              }, {
                "col1": "c",
                "col2": 3,
                "col3": 3,
                "col4": "new"
              }
           ]'::jsonb) AS properties 
    FROM inputtable
)
UPDATE inputtable 
SET properties = update_table.properties
FROM update_table
WHERE inputtable.data_point_id = update_table.data_point_id
Run Code Online (Sandbox Code Playgroud)