将JSON INSERT到两个表中并返回序列ID

时间:2017-10-05 16:32:52

标签: sql database postgresql insert plpgsql

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

我假设我的代码应该在my_data表中创建一个新记录(自动生成data_id并用我的JSON对象填充data_fields)但是它似乎我的假设不正确。

我缺少什么或者没有完全掌握?以下是复制我的设置的代码。

表:

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

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

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

但是你不需要 ($1::jsonb) 中的强制转换,因为输入参数已经输入jsonb

我建议使用数据修改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中使用标识符的混合大小写拼写。

相关: