sql - 执行 SELECT 或 INSERT

标签 sql postgresql concurrency

我想在 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/

相关文章:

sql - SQL 表连接中 ON 和 WHERE 子句的区别

java - 实现自定义连接池?

http - 语言 : MaxIdleConnsPerHost for many concurrent http connections?

java - notifyAll 操作的复杂性

SQL Server DATEADD 空值错误行为

在SELECT中通过GROUP BY在CASE中使用CASE的SQL。需要CASE值,但获得行值

mysql - 减去两个不存在行中带有负数的mysql表

postgresql - Airflow 将 postgres 数据库的所有表导出到 BigQuery

php - 拉维尔 5.6 : Create database schema using migration

php - 使用 php 从 postgresql 检索数据并将值存储在变量中