我想在 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)
}
最佳答案
表上没有并发写入负载,您可以简单地:
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
找到一行则不执行任何操作),因此我们不需要限制 1
。
但是,通常情况下,可能存在并发写入负载,并且您希望避免竞争条件。请参阅:
关于sql - 执行 SELECT 或 INSERT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66737782/