Postgres从insert中插入其他表中的值

时间:2017-09-20 09:56:49

标签: postgresql sql-insert database-sequence

我有两张桌子:

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的一些基础知识。我一直在这里搜索与嵌套插入相关的其他问题,但找不到我设法实际使用的东西,因此非常感谢代码示例。

2 个答案:

答案 0 :(得分:2)

这种插​​入链需要一个公用表表达式:

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列创建的序列的标准名称:

答案 1 :(得分:0)

我非常喜欢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() - 在语句之间编辑,也比 currval()

它也是最具可读性的解决方案。