我有两张桌子:
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的一些基础知识。我一直在这里搜索与嵌套插入相关的其他问题,但找不到我设法实际使用的东西,因此非常感谢代码示例。
答案 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()因为没有必要知道序列名称。
它也是最具可读性的解决方案。