【问题标题】:INSERT JSON into two tables and return serial ID将 JSON 插入两个表并返回序列号
【发布时间】:2017-10-05 16:32:51
【问题描述】:

我正在尝试将INSERT 一条新记录添加到 Postgres 9.6 数据库中,并获取该新插入记录的 ID 并将其传递给不同的表以获取外键引用。数据采用 JSON 格式,我想将 JSON blob 存储在行字段中,而不是将其解析出来。但是,我收到关于违反PRIMARY KEYNOT-NULL 约束的NULL 值的错误。

我假设我的代码应该在my_data 表中创建一个新记录(data_id 自动生成,data_fields 填充了我的 JSON 对象)但看来我的假设不正确.

我错过了什么或没有完全掌握?下面是复制我的设置的代码。

表格:

CREATE TABLE my_data(
  data_id SERIAL PRIMARY KEY,
  data_fields JSONB
);

CREATE TABLE request_data(
    request_id SERIAL PRIMARY KEY,
    request_timestamp TIMESTAMP WITH TIME ZONE,
    data_id INTEGER REFERENCES my_data(data_id),
    record_count INTEGER,
    completedStatus boolean
);

功能:

CREATE OR REPLACE FUNCTION updateData (
dataFields JSONB,
requestTimestamp TIMESTAMP WITH TIME ZONE,
recordCount INTEGER,
completedStatus boolean,
OUT new_record_id INTEGER
)
RETURNS integer AS $$
BEGIN
INSERT INTO my_data SELECT * FROM jsonb_populate_recordset(NULL::my_data, $1::jsonb) RETURNING data_id INTO new_record_id;
INSERT INTO request_data (request_timestamp, data_id, record_count, completed_status) VALUES($2, new_record_id, $3, $4);
END;
$$ LANGUAGE plpgsql;

呼叫:

SELECT updateData (
'[{"identity": "personA", "timestamp": "2017-09-15T20: 03: 12+00: 00"},
{"identity": "personB", "timestamp": "2017-09-15T20: 03: 12+00: 00"},
{"identity": "personC", "timestamp": "2017-09-15T20: 03: 12+00: 00"}]'
 '2017-09-29', 
 3, 
 true)

错误:

ERROR: null value in column "data_id" violates not-null constraint
SQL state: 23502
Detail: Failing row contains (null, null).

my_data 表的预期结果:

data_id     | data_fields
------------+------------------------------
    1       | [{"identity": "personA", "timestamp": "2017-09-15T20: 03: 12+00: 00"},{"identity": "personB", "timestamp": "2017-09-15T20: 03: 12+00: 00"},{"identity": "personC", "timestamp": "2017-09-15T20: 03: 12+00: 00"}]

request_data 表的预期结果:

request_id  |    request_timestamp     | data_id | record_count | completed_status
------------+--------------------------+---------+--------------+-------------------
    1       |   2017-09-29             |  1      |  3           |   true

【问题讨论】:

  • 你为什么使用这个 jsonb_populate_recordset ?尝试仅插入 my_data 值 ($1::jsonb),因为您将串行用于列 data_id。
  • 你提出了一个很好的观点。这是更好的解决方案。
  • 很高兴听到我能为您提供帮助。

标签: sql database postgresql insert plpgsql


【解决方案1】:

@Fahad 指出了主要的逻辑错误。

但您不需要在 ($1::jsonb) 中进行强制转换,因为输入参数已经输入了 jsonb

我会推荐一个 single 查询和一个数据修改 CTE,在一个简单的 SQL 函数中结合两个插入 - 而不是两个 INSERT 查询在 PL/pgSQL 函数之间有一个赋值.更短、更不容易出错、更快:

CREATE OR REPLACE FUNCTION update_data(data_fields jsonb
                                     , request_timestamp timestamptz
                                     , recordcount integer
                                     , completed_status boolean)
  RETURNS integer AS
$func$
   WITH ins1 AS (
      INSERT INTO my_data(data_fields)
      VALUES ($1)  -- no need to cast
      RETURNING data_id
      )
   INSERT INTO request_data(request_timestamp, data_id, record_count, completed_status)
   SELECT $2, i.data_id, $3, $4
   FROM   ins1 i
   RETURNING data_id
$func$  LANGUAGE sql;

我也统一为小写拼写。您混合了多种命名约定,导致completedStatuscompleted_status 不匹配。我的一贯建议是避免 Postgres 中标识符的大小写混合拼写。

相关:

【讨论】:

    【解决方案2】:

    @Fahad Anjum 指出了插入 json 的更好方法。我将INSERT 语句更改为INSERT INTO my_data (data_fields) values($1) RETURNING data_id INTO new_record_id;,它给了我需要的结果。

    【讨论】:

      猜你喜欢
      • 2019-03-25
      • 2019-04-19
      • 2020-10-14
      • 1970-01-01
      • 1970-01-01
      • 2021-05-23
      • 2019-11-28
      • 2014-02-26
      • 1970-01-01
      相关资源
      最近更新 更多