【问题标题】:If exist return id else insert in postgres [duplicate]如果存在返回 id 否则插入 postgres [重复]
【发布时间】:2013-06-18 15:38:51
【问题描述】:

我是 postgres 的新手,我不得不使用它来填充数据库。我无法提交我的实际代码以供参考,但我的程序是用 java 编写的,我正在尝试按照这些方式做一些事情。

IF EXISTS (SELECT 1 FROM TEST WHERE FOO = 2 and BAR = 3) 
 BEGIN
   SELECT TableID FROM TEST WHERE FOO = 2 and BAR = 3
 END
 ELSE
 BEGIN
   INSERT INTO TEST(FOO, BAR) VALUES(2, 3)
 END

我正在尝试按照这些方式做一些事情,因为我的程序只是解析一堆文件并填充数据库。我需要确保如果有人返回并在数据库不会包含重复条目的相同文件上再次运行该程序。与找到的此插入/记录关联的 id 用于填充链接表。我在另一个 stackoverflow 问题上发现了这个示例,它仅与 Microsoft SQL Server 2005 相关。我正在使用 postgres,它在 IF 的第一行就失败了。我了解不同的数据库语言的操作略有不同。有没有办法使用 postgres 执行 IF EXISTS 返回 ID else insert。

目前我正在检查该条目是否存在以及它是否不插入。但后来我不得不再次查询数据库以获取记录的 ID(如果它存在的话)。

int id = 0;
PrepareStatement ps = conn.prepare(SQL command, statement.generatekeys);  //syntax is not correct for the preparestatement but i'm not looking at my code and dont remember it off top of my head.
ResultSet rs = ps.executeUpdate();
if(rs.next()){
   if(rs.getGeneratedKeys().rows() > 0)  //not sitting at my code but there is a way to check if a key was generated from an insert
     id = rs.getGeneratedKeys()
   }else{
     id = rs.getInt(1);       
   }
}

更新取自 cmets:

更好的问题是有没有办法在不查询/检查 where 子句两次的情况下执行 if exists return id else insert。

我想避免进行两次WHERE 检查以从现有数据或新条目中获取我的 id。我的条件检查相当冗长,因为我的一些表包含超过 14 个属性。目前我所做的是在执行INSERT 时查询数据库(如果不存在)。如果我的 getGeneratedKeys().size() = 0 我知道 INSERT 因为它存在而失败,然后我使用原始查询中的相同 where 子句重新查询数据库并获取 id。

【问题讨论】:

  • 我认为我们将其标记为 dup 有点仓促;这不是一个 upsert,它是一个“如果没有找到就搜索并插入”。

标签: java postgresql


【解决方案1】:

这与UPSERTMERGE 操作密切相关,PostgreSQL 不直接支持该操作。 Upsert 在并发环境中比您预期的要复杂得多。

upsert 的大多数并发问题也适用于您想要执行的操作。如果一次有多个线程在执行更新,则您当前的代码是完全错误的。

阅读depesz's article on the topic,然后在堆栈溢出中搜索[postgresql] upsert[postgresql] mergethis SO post I wrote

您应该能够相当轻松地调整那里提供的 PL/PgSQL 函数来完成这项工作。不过,它只能在READ COMMITTED 隔离中正确运行。

【讨论】:

  • 我在看你提到的两件事,它在 postgres 中没有一个 if exists return id else insert 的例子,甚至指向一个可能有助于解释它是否可能在 postgres 中的方向。
  • @Jeremy 这是同一个问题的一个变体,有同样的问题。您可以调整stackoverflow.com/questions/17267417/… 中给出的 PL/PgSQL 函数以适应。
  • 如果我理解并正确阅读了这个例子,它需要我知道查询插入内容的 id。我的每个 if exists return id else insert 查询都在使用一个序列。所以在插入完成之前我不知道插入的 ID,我从 rs.getGeneratedKeys() 获取它。所以我不明白如何使示例成为您的参考工作。我检查它是否存在只是检查每个列字段是否与我尝试输入的相同。假设是我想返回所说的 id。
  • 更好的问题是“有没有办法在不查询/检查 where 子句两次的情况下执行 if exists return id else insert。” IE 没有进行两次 where 检查以从现有数据或新条目中获取我的 id。我的条件检查相当冗长,因为我的一些表包含超过 14 个属性。目前我所做的是在不存在时查询数据库一次插入。如果我的 getGeneratedKeys().size() = 0 我知道插入失败,因为它存在,然后我使用与原始查询相同的 where 子句重新查询数据库,获取 id。
  • @Jeremy 啊,这是对您真正想要的东西的更清晰的解释。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-28
  • 2013-08-14
  • 1970-01-01
  • 2019-09-06
  • 2021-10-03
  • 2013-12-27
相关资源
最近更新 更多