我正在尝试INSERT
一条新记录到 Postgres 9.6 数据库中,并获取该新插入记录的 ID 并将其传递到另一个表以供外键引用。数据是 JSON 格式,我想将 JSON blob 存储在行字段中,而不是将其解析出来。但是,我收到有关 NULL
值违反 PRIMARY KEY
的 NOT-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
最佳答案
@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;
我也统一到小写拼写。您混合使用了命名约定,导致 completedStatus
和 completed_status
不匹配。我的一贯建议是避免在 Postgres 中对标识符进行大小写混合拼写。
相关:
关于sql - 将 JSON 插入到两个表中并返回序列号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46590650/