我想用PostgreSQL编写类似于CASE
语句的东西,这样我就可以从一个表中执行SELECT
,如果什么都没有找到,我就想用INSERT
语句到表中。
我的示例表allocated_ideas
如下所示:
challenge_id | user_id | idea_id | round | is_completed
-------------+------------+----------------+-------+-------------
'5d956daa' | '9afbca19' | '3798826ae522' | 5 | false
我想在SQL函数中这样做:
SELECT EXISTS (
SELECT 1 from allocated_ideas ai
where ai.user_id = '9afbca19'
and ai.challenge_id = '5d956daa'
and ai.is_completed is false
如果该条件为真,则返回idea_id
。否则,将值插入到表中。伪代码:
if (above query is true) {
SELECT idea_id from allocated_ideas ai
where ai.user_id = '9afbca19'
and ai.challenge_id = '5d956daa'
and ai.is_completed is false
} else {
INSERT VALUES INTO allocated_ideas('67879', '46578', '978798', 6, false)
}
发布于 2021-03-22 07:23:29
在表上没有并发写入加载的情况下,您可以简单地:
WITH sel AS (
SELECT idea_id
FROM allocated_ideas
WHERE user_id = '9afbca19'
AND challenge_id = '5d956daa'
AND is_completed IS false
)
, ins AS (
-- spell out target columns!
INSERT INTO allocated_ideas (challenge_id, user_id, idea_id, round, is_completed)
SELECT '67879', '46578', '978798', 6, false
WHERE NOT EXISTS (TABLE sel) -- only when sel is empty!
-- RETURNING idea_id -- unused
)
TABLE sel;
修改数据的CTE ins
始终执行到完成,即使在最后的主命令中没有引用它。(一个简单的SELECT
不会在没有被引用的情况下被执行。)请参见:
如果您省略了INSERT
的目标列,它可能会默默(或嘈杂地)中断!
您未指定从INSERT
返回新的idea_id
。如果您需要它,您可能还希望能够区分不同的情况。为此,我添加了列op
:
WITH sel AS (
-- like above
, ins AS (
-- like above
RETURNING idea_id -- used now
)
SELECT 'sel' AS op, * FROM sel
UNION ALL
SELECT 'ins' AS op, * FROM ins;
查询只能返回一行,并且INSERT
在任何情况下都会执行(如果sel
找到行,则不执行任何操作),因此我们不需要LIMIT 1
。
但通常情况下,可能存在并发写入加载,并且您可能希望避免争用条件。请参见:
发布于 2021-03-22 06:24:40
以下是使用公用表表达式(CTE)完成此操作的一种方法:
WITH sel AS (
SELECT challenge_id, user_id, idea_id, round, is_completed
FROM allocated_ideas
WHERE user_id = '9afbca19' AND challenge_id = '5d956daa' AND is_completed = FALSE
), ins as (
INSERT INTO allocated_ideas (challenge_id, user_id, idea_id, round, is_completed)
SELECT '67879', '46578', '978798', 6, FALSE
WHERE NOT EXISTS (TABLE sel)
RETURNING *
)
SELECT * FROM sel
UNION ALL
SELECT * FROM ins
请注意,只有在没有并发事务在修改该表的情况下,这才有效。如果您希望并发写入,请先尝试使用ON冲突执行插入。
https://stackoverflow.com/questions/66737782
复制相似问题