在PostgreSQL中如何使用PreparedStatement的IN子句

25

我需要为Postgres数据库编写以下SQL查询:

DELETE FROM employee WHERE ename IN (?)

我想将ename作为包含多个员工名称的列表或字符串进行传递,例如"abc, bcd, efg"。如何设置值?

在Postgres中如何使用PreparedStatementIN子句?


如何在PostgreSQL中使用PreparedStatement的IN子句? - Ritesh
1
使用数组代替:where ename = any(<array parameter or constant here>)。有趣的是,PostgreSQL会将in子句内部转换为= any(...),可以在查询计划中看到这一点。 - Abelisto
可能是 PreparedStatement IN 子句的替代方法? 的重复问题。 - Mark Rotteveel
3个回答

26

有几种方法可以做到这一点。最好的方法是向预处理语句传递一个数组。另一种替代Nick答案的方法是传递一个正确的java.sql.Array值:

PreparedStatement pstmt = connection.prepareStatement(
    "DELETE FROM employee WHERE ename = ANY (?)");
String[] idList = new String[] {"abc", "bcd", "efg"};
Array ids = connection.createArray("varchar", idList);
pstmt.setArray(1, ids);

另一个选择是使用Postgres的字符串函数将逗号分隔的列表转换为数组。这可能是最简单的方法:

PreparedStatement pstmt = connection.prepareStatement(
     "DELETE FROM employee WHERE ename = ANY (string_to_array(?, ','))");
psmt.setString(1, "abc,bcd,efg");

请注意,逗号和值之间不能有空格!在string_to_array()完成其工作后,这些空格将是存储在数组中的值的一部分,因此比较可能是ename = ' bcd',如果列ename中没有前导空格(这是极有可能的),则会失败。

8
空格不仅是一个问题,如果逗号是值的一部分,那么你就会遇到麻烦。据我所知,没有办法对其进行转义。我能看出最好的选择是使用“the_leafs_just_won_the_stanley_cup”作为分隔符,因为这个短语在SQL诞生之前就不存在了,所以它不会成为任何值的一部分。 - Opux
2
运行良好,小改动:我不得不使用connection.createArrayOf而不是connection.createArray(保持参数相同)。谢谢。 - Andres

14

像这样:

DELETE FROM employee WHERE ename = ANY(?)
参数应该以数组字面值的形式进行格式化,例如 "{abc,bcd,efg}"。请参考数组文献了解更多信息。

1
数组字面量格式的部分救了我的一天。我试图在一个预处理语句中使用它。谢谢。 - Huzaifa

-10
你可能想尝试以下代码:
DELETE FROM employee 
 WHERE ename IN ('abc', 'bcd', 'efg')

我正在使用PreparedStatement,我们不知道需要删除多少条记录。这将是动态的。那么如何使用占位符呢?如果只有一个占位符,我们如何将值设置为列表或字符串呢? - Ritesh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接