我可以在另一个INSERT中使用INSERT ... RETURNING的返回值吗?

Eik*_*chu 67 postgresql sql-returning

这样的事情可能吗?

INSERT INTO Table2 (val)
VALUES ((INSERT INTO Table1 (name) VALUES ('a_title') RETURNING id));
Run Code Online (Sandbox Code Playgroud)

比如使用返回值作为值来在第二个表中插入一行并引用第一个表?

Den*_*rdy 81

你可以从Postgres 9.1开始:

with rows as (
INSERT INTO Table1 (name) VALUES ('a_title') RETURNING id
)
INSERT INTO Table2 (val)
SELECT id
FROM rows
Run Code Online (Sandbox Code Playgroud)

同时,如果您只对id感兴趣,可以使用触发器来执行此操作:

create function t1_ins_into_t2()
  returns trigger
as $$
begin
  insert into table2 (val) values (new.id);
  return new;
end;
$$ language plpgsql;

create trigger t1_ins_into_t2
  after insert on table1
for each row
execute procedure t1_ins_into_t2();
Run Code Online (Sandbox Code Playgroud)

  • 如何在返回的 id 旁边插入值?例如:INSERT INTO TABLE2(val1, val2, val3) (1, 2, SELECT id FROM rows) (3认同)
  • @MahmoudHanafy:要在返回的ID旁边插入值,您可以执行以下操作:INSERT INTO TABLE2(val1,val2,val3)SELECT id,1,2 FROM rows (2认同)
  • @PirateApp 刚刚测试!v12.4。如果第二个 INSERT 失败,第一个 INSERT 确实会回滚,但会跳过第一个 INSERT 的系列/自动增量 (2认同)

小智 49

这种情况的最佳做法.使用RETURNING … INTO.

INSERT INTO teams VALUES (...) RETURNING id INTO last_id;
Run Code Online (Sandbox Code Playgroud)

  • @Alec:我在[这个答案](https:// stackoverflow.com/a/12328286/4174789)。 (6认同)
  • 很有用。如果其他读者不清楚,您还可以`RETURNING col1, col2 INTO var1, var2` (3认同)
  • 这是真的吗?您链接到的文档的任何部分似乎都没有提到“ RETURNING ... INTO”。 (2认同)

Bhi*_*ndi 8

符合Denis de Bernardy给出的答案.

如果您希望之后返回id,并希望在Table2中插入更多内容:

with rows as (
INSERT INTO Table1 (name) VALUES ('a_title') RETURNING id
)
INSERT INTO Table2 (val, val2, val3)
SELECT id, 'val2value', 'val3value'
FROM rows
RETURNING val
Run Code Online (Sandbox Code Playgroud)


mu *_*ort 7

你可以使用这个lastval()功能:

nextval对于任何序列,最近获得的返回值

所以像这样:

INSERT INTO Table1 (name) VALUES ('a_title');
INSERT INTO Table2 (val)  VALUES (lastval());
Run Code Online (Sandbox Code Playgroud)

只要没有人调用nextval()INSERT之间的任何其他序列(在当前会话中),这将正常工作.

正如丹尼斯在下面提到的那样,我在上面发出警告,lastval()如果nextval()在你的INSERT之间使用另一个序列,使用可能会让你陷入困境.如果在序列上Table1手动调用INSERT触发器,nextval()或者更有可能在具有主键SERIALBIGSERIAL主键的表上执行INSERT,则可能发生这种情况.如果你想成为一个真正的偏执(一件好事,他们真的是你终究得到你),那么你可以使用,currval()但你需要知道相关序列的名称:

INSERT INTO Table1 (name) VALUES ('a_title');
INSERT INTO Table2 (val)  VALUES (currval('Table1_id_seq'::regclass));
Run Code Online (Sandbox Code Playgroud)

自动生成的序列通常被命名为t_c_seq其中t是表名称,c是列名,但你总是可以通过进入发现psql,说:

=> \d table_name;
Run Code Online (Sandbox Code Playgroud)

然后查看相关列的默认值,例如:

id | integer | not null default nextval('people_id_seq'::regclass)
Run Code Online (Sandbox Code Playgroud)

仅供参考:lastval()或多或少是MySQL的PostgreSQL版本LAST_INSERT_ID.我只提到这一点,因为很多人比PostgreSQL更熟悉MySQL,所以链接lastval()到熟悉的东西可能会澄清事情.

  • 但是,最好使用currval(),以防table1上的触发器执行后续插入. (2认同)

And*_*s B 5

DO $$
DECLARE tableId integer;
BEGIN
  INSERT INTO Table1 (name) VALUES ('a_title') RETURNING id INTO tableId;
  INSERT INTO Table2 (val) VALUES (tableId);
END $$;
Run Code Online (Sandbox Code Playgroud)

用psql测试(10.3,服务器9.6.8)