Postgres 插入其他 table 中的插入值

Postgres insert value from insert in other table

我有两个表:

CREATE TABLE tbl_a (
id serial primary key NOT NULL,
name text NOT NULL,
tbl_b_reference NOT NULL
)

CREATE TABLE tbl_b (
id serial primary key NOT NULL,
status text)

我想插入两个。一个在 tbl_b 中,然后在我插入 tbl_a.

时使用该插入中的 ID

我试过这个:

INSERT INTO tbl_a(name, tbl_b_reference) 
VALUES ("myName", (INSERT INTO tbl_b (status) VALUES ('OK') RETURNING id));

但我只收到指向第二个的语法错误 "INTO"

ERROR: syntax error at or near "INTO" Position: 68

从这里我该何去何从?是否可以在不编写永久函数或创建触发器的情况下执行此操作?我是 postgres 的新手,只知道 MySQL/MariaDB 的一些基础知识。我一直在这里搜索与嵌套插入相关的其他问题,但找不到我设法实际使用的东西,因此非常感谢代码示例。

对于这种插入链接,您需要一个通用的 table 表达式:

with ta as (
  INSERT INTO tbl_b (status) VALUES ('OK') 
  RETURNING id
)
INSERT INTO tbl_a (name, tbl_b_reference) 
VALUES ('myName', (select id from ta));

另一种选择是简单地使用lastval()函数来引用最后生成的序列值:

INSERT INTO tbl_b (status) VALUES ('OK');
INSERT INTO tbl_a (name, tbl_b_reference) 
  VALUES ('myName', lastval());

请注意,您不能有任何其他语句在这两者之间生成序列值。

或使用 currval() 函数:

INSERT INTO tbl_b (status) VALUES ('OK');
INSERT INTO tbl_a (name, tbl_b_reference) 
  VALUES ('myName', currval('tbl_b_id_seq'));

'tbl_b_id_seq' 是 Postgres 用于为 serial 列创建的序列的标准名称:

我真的很喜欢 a_horse_with_no_name 上面提到的 WITH ... AS 解决方案,因为这是唯一在一条语句中实现这一点的原子解决方案。

但是,如果您觉得在两个语句中这样做很好,那么还有第四种简单的方法:使用子查询和 max().

INSERT INTO tbl_b (status) VALUES ('OK');
INSERT INTO tbl_a (name, tbl_b_reference) 
  VALUES ('myName', (SELECT max(id) FROM tbl_b));

我个人觉得这比 lastval() 好,因为它只取决于这个特定的序列不在语句之间被 next()-ed 并且也比 currval() 因为不需要知道序列名称。

而且它也是最易读的解决方案。