我用下面的简单表格演示了这个问题。 (实际的表和 JSON 文档有更多字段。)
CREATE table contact (
id bigint PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
firstname VARCHAR,
lastname VARCHAR,
birthday timestamp with time zone NOT NULL
);
我正在尝试使用
jsonb_populate_record
: 从 JSONB 插入此表
INSERT INTO contact (firstname, lastname, birthday)
SELECT (jsonb_populate_record(NULL::contact,
'{
"firstname": "John",
"lastname": "Doe",
"birthday": "2023-09-28"
}'
)).*;
此操作失败并出现错误:
错误:INSERT 的表达式多于目标列
第 1 行:...O 联系人(名字、姓氏、生日)选择 jsonb_popu...
我知道错误来自不包含
id
键和值的 JSONB。因此,jsonb_populate_record
函数正在使用 id
列创建一条记录,但由于 INSERT
中未指定它,因此失败。
我尝试将
id
添加到 INSERT INTO contact (id, ....
中,但失败并出现错误,id
为空(因为我的 JSONB 中没有任何 id
)。
我怎样才能让它工作,以便
id
是表中指定的 GENERATED BY DEFAULT AS IDENTITY
?
编辑:
我找到了解决方案:
INSERT INTO contact (id, firstname, lastname, birthday)
SELECT (jsonb_populate_record(NULL::contact, jsonb_set('{
"firstname": "John",
"lastname": "Doe",
"birthday": "2023-09-28"
}', '{id}', to_jsonb(nextval(pg_get_serial_sequence('contact', 'id')))))).*;
然而,此后生成的
id
似乎跳过了4位数字:
select * from contact;
id | firstname | lastname | birthday
----+-----------+----------+------------------------
10 | John | Doe | 2023-09-28 00:00:00-04
14 | John | Doe | 2023-09-28 00:00:00-04
18 | John | Doe | 2023-09-28 00:00:00-04
22 | John | Doe | 2023-09-28 00:00:00-04
知道为什么以及如何避免这种情况吗?
您可以使用不同的函数,例如 jsonb_to_record():
INSERT INTO contact (firstname, lastname, birthday)
SELECT firstname
, lastname
, birthday
FROM jsonb_to_record(
'{
"firstname": "John",
"lastname": "Doe",
"birthday": "2023-09-28"
}'::jsonb
) AS j(firstname text, lastname text, birthday date);