【问题标题】:Convert a String to pass multiple values in SQL WHERE IN clause in Java转换字符串以在 Java 中的 SQL WHERE IN 子句中传递多个值
【发布时间】:2021-12-07 03:09:54
【问题描述】:

我有一个字符串参数fruit,它应该接受逗号分隔的字符串,例如:"Banana, Apple, Orange"。如何将此字符串拆分为 3 个数据,例如 "Banana", "Apple", "Orange",以便可以将其传递给下面的 SQL:

StringBuilder sql = new StringBuilder(
"SELECT * FROM fruit f where ");

 if (!inputParameters.getFruit().isEmpty()) {
   sql.append("f.name IN (:fruit) ");
   parameterSource.addValue("fruit", inputParameters.getFruit());
 ) 
}

在这里,我想在 SQL IN 子句中传递 getFruit 的值,该子句已经转换为 3 个数据:"Banana", "Apple", "Orange" 而不是只有 1 个字符串数据 "Banana, Apple, Orange"

【问题讨论】:

  • 您可以使用"Banana, Apple, Orange".split(","),这样您就可以得到这三个字符串的数组,然后您可以对每个字符串执行.trim() 以删除空格
  • 但是我的 setFruit 是 String,当我尝试这样做时出现错误:inputParameters.setFruit(fruits.split(","); fruits object contains the "Banana, Apple, Orange"
  • inputParameters.getFruit()实际返回的是什么类型?
  • inputParameters.getFruit() 返回一个字符串。我想要实现的是我上面的 SQL 查询应该接受 3 个数据“香蕉”、“苹果”、“橙色”,而不是只有一个字符串
  • 使用从拆分中获得的数据 (String[]),如果您愿意,您必须做一个字符串模板,每个水果都有 0,1,2 个索引

标签: java sql spring postgresql spring-mvc


【解决方案1】:

我认为这可以帮助你:

String oneStringFruit = "Banana, Apple, Orange";
StringBuilder sql = new StringBuilder("SELECT * FROM fruit f where f.name IN (");
String[] fruits = oneStringFruit.split(",");

Set.of(fruits).forEach(fruit -> sql.append("'").append(fruit.trim()).append("', "));
sql.replace(sql.lastIndexOf(","), sql.lastIndexOf(",") + 1, ")");
System.out.println(sql);

享受吧!

【讨论】:

  • 我在这部分出现错误Set<String> fruits = inputParameters.getFruit(),因为inputParameters.getFruit() 类型是字符串
  • 你的inputParameters.getFruit()是什么类型的?
  • 只有一个字符串?我以为是 3:...converted into 3 data: "Banana", "Apple", "Orange"
  • 是的,我的参数fruit 是String 类型,有1 个String "Banana, Apple, Orange"。我想在SQL 中将它作为"Banana", "Apple", "Orange" 之类的3 个数据传递
  • 好的!我现在明白了,它适用于我对答案所做的更新。
【解决方案2】:

最简单的方法是将整个 "Banana, Apple, Orange" 字符串传递给 postgres 并让 postgres 通过 string_to_array 和 unnest() 分解字符串:

StringBuilder sql = new StringBuilder(
"SELECT * FROM fruit f where ");

if (!inputParameters.getFruit().isEmpty()) {
  sql.append("f.name IN (SELECT UNNEST(string_to_array(:fruit, ', ')) ");
  parameterSource.addValue("fruit", inputParameters.getFruit());
  ) 
}

string_to_array:fruit 字符串分解为一个数组,UNNEST 将该数组转换为适合 IN 的记录集

【讨论】:

  • 我之前确实这样做过,并且能够实现我想要的,但是我被要求不要在 SQL 级别进行检查,而应该直接在 Java 代码中进行检查
【解决方案3】:

在 SQL 中,字符串文字需要用单引号字符括起来。因此,您想用以下内容替换 :fruit(在 SQL 查询的文本中)

'Banana','Apple','Orange'

换句话说,你不需要拆分getFruit方法返回的字符串,你只需要稍微改变一下。下面的代码就是这样做的。

String fruit = "Banana, Apple, Orange"; // value returned from method `getFruit`
String sql = "SELECT * FROM fruit f where f.name IN (:fruit)";
System.out.println(sql.replaceFirst(":fruit", fruit.replaceAll("([A-Z][a-z]+)", "'$1'")));

运行上面的代码会产生以下结果:

SELECT * FROM fruit f where f.name IN ('Banana', 'Apple', 'Orange')

【讨论】:

  • 如果我将在代码级别而不是 SQL 级别实现它,我还能使用这个确切的代码吗?其中 fruit 显示的值是 Banana, Apple, Orange 当我使用 System.out.print(inputParameters.getFruit())
  • @DanielFord 我不明白您所说的代码级别SQL 级别 是什么意思。最后,您需要将一个字符串传递给 PostgreSQL,并且该字符串需要包含有效的 SQL。
  • 我尝试使用您的建议,但只有在请求单个值时才能获取数据。但是当我请求多个值时,它根本不获取数据
  • @DanielFord 我无权访问您的数据库,您没有发布表 FRUIT 的结构,您也没有发布 minimal reproducible example 但也许这个 db<>fiddle 将有助于演示我的答案中 SQL 查询的正确性。我根据您问题中的数据回答了您提出的问题。我不知道为什么它对您不起作用,因为我无法确切地看到您在做什么。显然你省略了一些细节。
猜你喜欢
  • 2018-06-22
  • 1970-01-01
  • 1970-01-01
  • 2011-10-20
  • 1970-01-01
  • 1970-01-01
  • 2012-07-16
  • 2018-02-16
  • 2018-11-03
相关资源
最近更新 更多