[英]Is it possible to capture the ID of a created row in postgres to use in the same query?
TL; DR,我想知道是否可以在 postgres 中创建一个资源,然后创建另一个引用它的资源,所有这些都在同一个语句中。 我想这样做是为了减少往返时间并简化我的后端逻辑。
我目前有两个资源,foo 和 bar。 Bar 是引用它的 foo 的子资源:
CREATE TABLE foos (
id serial PRIMARY KEY,
name VARCHAR ( 50 ) UNIQUE NOT NULL
);
CREATE TABLE bars (
id serial PRIMARY KEY,
name VARCHAR ( 50 ) NOT NULL,
description VARCHAR ( 50 ),
foo_id int NOT NULL,
FOREIGN KEY (foo_id)
REFERENCES foos (id),
UNIQUE (foo_id, name)
);
我目前有以下 sql 语句在端点v1/foos/{foo_name}/bars/{bar_name}
上插入 foo 和 bar:
WITH upsert_foo AS
(
INSERT INTO "foos"
("name")
VALUES
($1)
ON CONFLICT ("name") DO NOTHING
),
upsert_bar AS
(
INSERT INTO "bars"
("name", "description", "foo_id" )
VALUES
($2, $3,
(SELECT "id" FROM "foos" WHERE "name" = $1) )
ON CONFLICT ("name", "foo_id") DO
UPDATE SET
"description" = EXCLUDED."description",
RETURNING *
)
SELECT upsert_bar.*;
当用户 upsert 一个 bar 时,如果它不存在,则应创建一个名称来自 URI 的 foo,如果它不存在则应创建该 bar。 否则,应该更新栏。
但是,此语句仅适用于更新情况,即 foo 资源已经存在。 新创建的 foo 似乎没有出现在(SELECT "id" FROM "foos" WHERE "name" = $1)
中。
有没有办法可以捕获已创建(或已存在)的 foo 的 ID 并在创建栏 object 时使用它?
我唯一能想到的就是将其分解为单独的操作:
INSERT INTO
"foos" ("name")
VALUES
($1)
ON CONFLICT ("name") DO UPDATE
SET name = foos.name
RETURNING id;
上面有一个丢弃的UPDATE
用于捕获id
值。 将此值保存到变量中以用作下面的$4
。
然后:
INSERT INTO
"bars" ("name", "description", "foo_id" )
VALUES
($2, $3, $4)
ON CONFLICT ("name", "foo_id") DO UPDATE
SET "description" = EXCLUDED."description"
RETURNING *
我设法在一个语句中完成了这项工作,但这有点复杂:
WITH insert_foo AS
(
INSERT INTO "foos"
("name")
VALUES
($1)
ON CONFLICT ("name") DO NOTHING RETURNING *
),
upsert_foo AS
(
SELECT * FROM insert_foo
UNION
SELECT * FROM foos WHERE "name"=$1
),
upsert_bar AS
(
INSERT INTO "bars"
("name", "description", "foo_id" )
VALUES
($2, $3, (SELECT "id" FROM upsert_foo WHERE name=$1) )
ON CONFLICT ("name", "foo_id") DO
UPDATE SET
"description" = EXCLUDED."description"
RETURNING *
)
SELECT * FROM upsert_bar;
基本上,插入的结果应该与常规的 select 查询联合,其中只有一个包含一行,具体取决于 foo 是否已经存在。 然后我可以 select 来自此联合查询结果的 id。
我想向 Adrian Klaver 大声喊叫,因为他指出了我正确的方向以及这个答案: https://stackoverflow.com/a/62205017/4600258
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.