我是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的第一行就失败了。我理解不同的数据库语言操作略有不同。有没有办法做一个IF EXISTS返回ID,否则使用postgres插入。
目前我正在检查条目是否存在以及是否插入。但是,我必须再次查询数据库,以获得它存在的记录的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);
}
}
更新取自评论:
更好的问题是有没有办法在没有查询/检查where子句两次的情况下执行if exists return else else。
我希望避免两次WHERE
检查,以从现有数据或新条目中获取我的ID。我的条件检查相当冗长,因为我的一些表包含超过14个属性。目前我所做的是在执行INSERT
后查询数据库(如果不存在)。如果我的getGeneratedKeys().size() = 0
我知道INSERT
失败,因为它存在,然后我使用原始查询中的相同where子句重新查询数据库并获取id。
答案 0 :(得分:3)
这与UPSERT
或MERGE
操作密切相关,PostgreSQL不直接支持此操作。在并发环境中,Upsert比您期望的要复杂得多。
upsert的大多数并发问题也适用于您想要做的事情。当有多个线程同时进行更新时,您当前的代码完全错误。
阅读depesz's article on the topic,然后搜索Stack Overflow for [postgresql] upsert
或[postgresql] merge
和this SO post I wrote。
你应该能够相当容易地调整那里给出的PL / PgSQL函数来完成这项工作。但它只能在READ COMMITTED
隔离中正确运行。