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。
- 我觉得我们把这个标记为dup有点仓促;这并不是一个大麻烦,它是一个"如果找不到就搜索并插入"。
这与UPSERT或MERGE操作密切相关,PostgreSQL不直接支持该操作。在并发环境中,upsert比您预期的要复杂得多。
upsert的大多数并发问题也适用于您想要做的事情。当多个线程同时进行更新时,您当前的代码是完全错误的。
阅读depesz关于这个主题的文章,然后搜索[postgresql] upsert或[postgresql] merge的堆栈溢出,这就是我写的文章。
您应该能够相当容易地适应给定的pl/pgsql函数来完成这项工作。不过,它只能在READ COMMITTED隔离状态下正常运行。
- 我在看你提到的两件事,它在Postgres中没有一个if-exist返回id-else-insert的例子,甚至没有一个可以帮助解释postgres中是否可能存在的方向。
- @杰里米是同一个问题的变种,也有同样的问题。您可以调整stackoverflow.com/questions/17267417/…中给出的pl/pgsql函数来适应。
- 如果我正确理解并阅读了这个示例,那么就需要知道在查询插入内容时使用的ID。我的每个if exist返回id else insert查询都使用seqence。所以我不知道插入的ID,直到它完成后,我从rs.getGeneratedKeys()获取它。所以我不知道如何让这个例子成为你的参考。我检查它是否存在只是检查每个列字段是否与我尝试输入的字段相同。假设是的话,我想把所说的身份证还给你。
- 更好的问题是"有没有一种方法可以在不查询/检查两次WHERE子句的情况下执行if exist返回id else insert。"即不执行两次WHERE检查以从现有数据或新条目中获取我的ID。我的条件检查相当冗长,因为我的一些表包含14个以上的属性。目前我所做的是在执行插入操作(如果不存在)后查询数据库。如果我的getGeneratedKeys().size()=0,我知道插入失败,因为它存在,然后我用原始查询中获取ID的相同WHERE子句重新查询数据库。
- @杰里米啊,这是对你真正想要什么的更清楚的解释。
- 那么,从性能上讲,有没有一种更有效的插入方式呢?我从中提取信息来填充数据库的数据集非常大。我担心的是,通过在那里执行两次检查,我会显著地减慢进程。
- 我实际上找到了一种方法来解决这个问题,不确定现在的问题是性能是否更好。在stackoverflow.com/questions/17454748/…中给出了实现这一点的解决方案。
- 如何通过引用包含雨篷的StackOverflow上的另一个问题将此问题标记为雨篷?简单地说,我发现了一个解决方案,我自己把它贴在了另一个关于优化和速度的问题上。但我想结束这个问题,让人们寻找相同的解决方案来查看另一个帖子?解决方案在上面的链接中提供。
- @杰里米可以发表你自己的答案,引用并总结一下。或者"标记"你的问题,如果你觉得它几乎是相同的,请一位主持人将其作为另一个问题的副本关闭。