3

I have two tables:

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)

I want to do two inserts. One in tbl_b, and then use the id from that insert when I do my insert into tbl_a.

I've tried this:

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

but I only get a syntax error pointing at the second "INTO"

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

Where do I go from here and is it possible to do this without writing permanent functions or creating triggers? I'm new to postgres and just know some basics of MySQL/MariaDB. I've been searching around here for other questions related to nested inserts but couldn't find something that I managed to actually use, so code examples would be much appreciated.

4

2 回答 2

6

对于这种插入链接,您需要一个公共表表达式:

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

于 2017-09-20T10:01:08.147 回答
-1

我真的很喜欢上面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()更好,因为不需要知道序列名称。

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

于 2017-09-20T12:15:07.050 回答