如何在 DELETE 后有条件地 UPDATE/INSERT 找不到行?
How to conditionally UPDATE/INSERT after DELETE that doesn't find rows?
我正在尝试在删除不同 table 中的值后更新 table。
这是我对这个问题的简化函数查询:
create function updateoutfit(_id uuid, _title text DEFAULT NULL::text, _garments json)
returns TABLE(id uuid, title text, garments json)
language sql
as
$$
WITH del AS (DELETE FROM outfit_garment WHERE outfit_garment.outfit_id = _id RETURNING outfit_id),
updateOutfit AS (
UPDATE outfit SET
title = _title
FROM del
WHERE outfit.id = _id
RETURNING id, title
),
saveOutfitGarment as (
insert into outfit_garment (position_x, outfit_id)
SELECT "positionX",
(SELECT updateOutfit.id from updateOutfit)
from json_to_recordset(_garments) as x("positionX" float,
outfit_id uuid) RETURNING json_build_object('positionX', position_x) as garments)
SELECT id,
title,
json_agg(garments)
from updateOutfit as outfit,
saveOutfitGarment as garments
group by id, title;
$$;
如果有 outfit_id 从 delete:
返回,则效果很好
DELETE FROM outfit_garment WHERE outfit_garment.outfit_id = _id RETURNING outfit_id
但如果没有要删除的行,则会失败。我试过这样的事情:
DELETE FROM outfit_garment WHERE outfit_garment.outfit_id = '1234' RETURNING (SELECT '1234' as outfit_id );
但它仍然是 returns 0 行。
有没有解决这个问题的方法或更好的方法?
我正在使用 Postgres 13.2
如果 DELETE
没有找到符合条件的行,它的 RETURNING
子句 returns 没有行。
标题要求“有条件地UPDATE/INSERT after DELETE”,但是body抱怨它“如果没有要删除的行。如果要删除的行的存在不是条件,那么条件是什么?
冒险出门,这可能就是你想要的:
CREATE FUNCTION updateoutfit(_id UUID, _title text DEFAULT NULL::text, _garments json)
RETURNS TABLE (id UUID, title text, garments json)
LANGUAGE sql AS
$func$
DELETE FROM outfit_garment WHERE outfit_id = _id; -- DELETE if exists
INSERT INTO outfit (id, title) -- UPSERT outfit
VALUES (_id, _title)
ON CONFLICT (id) DO UPDATE
SET title = EXCLUDED.title;
WITH ins AS ( -- INSERT new rows in outfit_garment
INSERT INTO outfit_garment (position_x, outfit_id)
SELECT "positionX", _id
FROM json_to_recordset(_garments) AS x("positionX" float) -- outfit_id UUID was unused!
RETURNING json_build_object('positionX', position_x) AS garments
)
SELECT _id, _title, json_agg(garments)
FROM ins
GROUP BY id, title;
$func$;
它从 table outfit_garment
中删除给定 UUID 的所有行,然后在 table outfit
中插入或更新一行,最后添加新的详细信息行在 table outfit_garment
中。 _garments
中传递的任何 outfit_id
都将被忽略。
然后它 returns 一行,所有服装合并成一个 JSON 值。
感谢您的查询@Erwin Brandstetter 我解决了我的问题。
这是我的最终查询:
create function updateoutfit(_id uuid, _garments json, _title text DEFAULT NULL::text)
returns TABLE
(
id uuid,
title text,
garments json
)
language sql
as
$$
DELETE
FROM outfit_garment
WHERE outfit_id = _id;
WITH upd as (
UPDATE outfit
SET title = _title
WHERE outfit.id = _id
RETURNING id, title
),
ins AS (
insert into outfit_garment (position_x, garment_id, outfit_id)
SELECT "positionX",
"id",
_id
from json_to_recordset(_garments) as x("positionX" float,
"id" uuid
) RETURNING json_build_object('positionX', position_x,
'garmentId',
garment_id
) as garments
)
SELECT id,
title,
json_agg(garments)
from upd,
ins
group by id, title;
$$;
我正在尝试在删除不同 table 中的值后更新 table。
这是我对这个问题的简化函数查询:
create function updateoutfit(_id uuid, _title text DEFAULT NULL::text, _garments json)
returns TABLE(id uuid, title text, garments json)
language sql
as
$$
WITH del AS (DELETE FROM outfit_garment WHERE outfit_garment.outfit_id = _id RETURNING outfit_id),
updateOutfit AS (
UPDATE outfit SET
title = _title
FROM del
WHERE outfit.id = _id
RETURNING id, title
),
saveOutfitGarment as (
insert into outfit_garment (position_x, outfit_id)
SELECT "positionX",
(SELECT updateOutfit.id from updateOutfit)
from json_to_recordset(_garments) as x("positionX" float,
outfit_id uuid) RETURNING json_build_object('positionX', position_x) as garments)
SELECT id,
title,
json_agg(garments)
from updateOutfit as outfit,
saveOutfitGarment as garments
group by id, title;
$$;
如果有 outfit_id 从 delete:
返回,则效果很好DELETE FROM outfit_garment WHERE outfit_garment.outfit_id = _id RETURNING outfit_id
但如果没有要删除的行,则会失败。我试过这样的事情:
DELETE FROM outfit_garment WHERE outfit_garment.outfit_id = '1234' RETURNING (SELECT '1234' as outfit_id );
但它仍然是 returns 0 行。
有没有解决这个问题的方法或更好的方法?
我正在使用 Postgres 13.2
如果 DELETE
没有找到符合条件的行,它的 RETURNING
子句 returns 没有行。
标题要求“有条件地UPDATE/INSERT after DELETE”,但是body抱怨它“如果没有要删除的行。如果要删除的行的存在不是条件,那么条件是什么?
冒险出门,这可能就是你想要的:
CREATE FUNCTION updateoutfit(_id UUID, _title text DEFAULT NULL::text, _garments json)
RETURNS TABLE (id UUID, title text, garments json)
LANGUAGE sql AS
$func$
DELETE FROM outfit_garment WHERE outfit_id = _id; -- DELETE if exists
INSERT INTO outfit (id, title) -- UPSERT outfit
VALUES (_id, _title)
ON CONFLICT (id) DO UPDATE
SET title = EXCLUDED.title;
WITH ins AS ( -- INSERT new rows in outfit_garment
INSERT INTO outfit_garment (position_x, outfit_id)
SELECT "positionX", _id
FROM json_to_recordset(_garments) AS x("positionX" float) -- outfit_id UUID was unused!
RETURNING json_build_object('positionX', position_x) AS garments
)
SELECT _id, _title, json_agg(garments)
FROM ins
GROUP BY id, title;
$func$;
它从 table outfit_garment
中删除给定 UUID 的所有行,然后在 table outfit
中插入或更新一行,最后添加新的详细信息行在 table outfit_garment
中。 _garments
中传递的任何 outfit_id
都将被忽略。
然后它 returns 一行,所有服装合并成一个 JSON 值。
感谢您的查询@Erwin Brandstetter 我解决了我的问题。
这是我的最终查询:
create function updateoutfit(_id uuid, _garments json, _title text DEFAULT NULL::text)
returns TABLE
(
id uuid,
title text,
garments json
)
language sql
as
$$
DELETE
FROM outfit_garment
WHERE outfit_id = _id;
WITH upd as (
UPDATE outfit
SET title = _title
WHERE outfit.id = _id
RETURNING id, title
),
ins AS (
insert into outfit_garment (position_x, garment_id, outfit_id)
SELECT "positionX",
"id",
_id
from json_to_recordset(_garments) as x("positionX" float,
"id" uuid
) RETURNING json_build_object('positionX', position_x,
'garmentId',
garment_id
) as garments
)
SELECT id,
title,
json_agg(garments)
from upd,
ins
group by id, title;
$$;