关于java:如果存在返回id,则在postgres中插入

If exist return id else insert in postgres

本问题已经有最佳答案,请猛点这里访问。

我是Postgres的新手,我必须用它填充一个数据库。我不能提交我的实际代码作为参考,但我的程序是在Java,我试图做一些沿着这些线。

1
2
3
4
5
6
7
8
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(如果存在的话)。

1
2
3
4
5
6
7
8
9
10
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);      
   }
}

更新来自注释:

更好的问题是,有一种方法可以在不查询/检查两次WHERE子句的情况下执行if exist返回id else insert。

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


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

upsert的大多数并发问题也适用于您想要做的事情。当多个线程同时进行更新时,您当前的代码是完全错误的。

阅读depesz关于这个主题的文章,然后搜索[postgresql] upsert[postgresql] merge的堆栈溢出,这就是我写的文章。

您应该能够相当容易地适应给定的pl/pgsql函数来完成这项工作。不过,它只能在READ COMMITTED隔离状态下正常运行。