首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >执行选择或插入操作

执行选择或插入操作
EN

Stack Overflow用户
提问于 2021-03-22 05:32:53
回答 2查看 126关注 0票数 2

我想用PostgreSQL编写类似于CASE语句的东西,这样我就可以从一个表中执行SELECT,如果什么都没有找到,我就想用INSERT语句到表中。

我的示例表allocated_ideas如下所示:

代码语言:javascript
运行
复制
challenge_id | user_id    | idea_id        | round | is_completed
-------------+------------+----------------+-------+-------------
 '5d956daa'  | '9afbca19' | '3798826ae522' |   5   | false

我想在SQL函数中这样做:

代码语言:javascript
运行
复制
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。否则,将值插入到表中。伪代码:

代码语言:javascript
运行
复制
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)
}
EN

回答 2

Stack Overflow用户

发布于 2021-03-22 07:23:29

在表上没有并发写入加载的情况下,您可以简单地:

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
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

但通常情况下,可能存在并发写入加载,并且您可能希望避免争用条件。请参见:

票数 2
EN

Stack Overflow用户

发布于 2021-03-22 06:24:40

以下是使用公用表表达式(CTE)完成此操作的一种方法:

代码语言:javascript
运行
复制
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冲突执行插入。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66737782

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档