繁体   English   中英

如何在 sql 查询中传递 List

[英]How to pass List in sql query

我有值(例如1, 2, 3 ),我想将该列表传递给 SQL 查询:

"select name from tbl where id in" + list 

我怎样才能做到这一点?

您必须将您的列表直接放入 sql 语句

例子:

String sql="select name from tbl where id in ("+StringUtils.join(list, ',')+")";
Statement st=connection.createStatement();
st.execute(sql);

我在您对评论的回复中看到您正在使用 HQL。 如果是这种情况,Hibernate 人员可以让您轻松完成此操作,只需在查询中指定:

where id in (:ids)

然后使用setParameterList("ids", list)传递您的列表。 Hibernate 将为您完成所有扩展!

SQL 语法为:

select name from tbl where id in (1,2,3)

您所要做的就是构建逗号分隔的项目列表并将其插入字符串中。

哦,还有强制性的 sql 字符串构建警告:不要!

这取决于您如何构建 sql。 如果您自己构建它(坏主意),您需要使 sql 看起来像 -

... where id in (1,2,3)...

因为在您的评论中您指定了 hibernate hql,类似于 -

Query query = session.createSQLQuery("from User where id in :ids ");
query.setParameter("ids", idsList);
List list = query.list();

应该让你开始。 注意User是您映射到要查询的表的 Object 的名称。

使用 java 8 及以上:

String inClause = list.stream().map(id-> String.valueOf(id)).collect(toStringJoiner(","));
String sql = "select name from tbl where name in (" + inClause + ")";
private static String sqlFormatedList(List<String> list){
     StringBuilder sb = new StringBuilder();
     sb.append("('");
     for (String i : list){
       sb.append(i+"','");
     }
     sb.deleteCharAt(sb.length() -1);
     sb.deleteCharAt(sb.lastIndexOf(","));
     sb.append(")");
     return sb.toString();
    }

将列表作为逗号分隔列表传入,并使用拆分 function 将其拆分为临时表变量。

CREATE FUNCTION dbo.Split (@sep char(1), @s varchar(512))
RETURNS table
AS
RETURN (
    WITH Pieces(pn, start, stop) AS (
      SELECT 1, 1, CHARINDEX(@sep, @s)
      UNION ALL
      SELECT pn + 1, stop + 1, CHARINDEX(@sep, @s, stop + 1)
      FROM Pieces
      WHERE stop > 0
    )
    SELECT pn,
      SUBSTRING(@s, start, CASE WHEN stop > 0 THEN stop-start ELSE 512 END) AS s
    FROM Pieces
  )

String sqlQuery = "从 tbl 中选择名称,其中 id 在" + sqlFormatedList(list);

private String sqlFormatedList(List<Integer> list){
 StringBuilder sb = new StringBuilder();
 sb.append("(");
 for (Integer i : list){
   sb.append(i+",");
 }
 sb.deleteCharAt(sb.length() -1);
 sb.append(")");
 return sb.toString();
}

您可以编写类似的代码,然后将 uuidsWithRequiredPattern 传递给 SQL。在下面的示例中,我要求 uuid 以单引号为前缀,以单引号为后缀,并以逗号分隔。

List<UUID> uuidList = Arrays.asList("581394be-6a27-11ea-bc55-0242ac130003","681394be-6a27-11ea-bc55-0242ac130003")
String uuidsWithRequiredPattern = uuidList.stream()
                .map(UUID::toString)
                .collect(Collectors.joining(",", "'", "'"));

我知道这已经过去很长时间了,但这是我在寻找该问题的解决方案时返回的页面。 由于某种原因,似乎所有答案都不完美(包括 SQL 注入的可能性,这是一个真正的问题)。所以,这是我的解决方案:-

/**
 * Checks if this range exists in the database already.
 * If it does, it will return the original name.
 * @param products the list of product names to check
 * @return  The range's name in the database
 * @throws SQLException if SQL fails
 *   (or if it exists but with multiple names)
 */
private String getOriginalName(final List<String> products)throws SQLException {
  if (products.isEmpty()) {
    throw new SQLException("Cannot check an empty list");
  }
  try (Connection connection = ConnectionPoolConfigRulesUtils.getConnection();
      PreparedStatement statement = connection.prepareCall(
          "SELECT [rangeName] FROM [dbo].[products] WHERE [productName] IN ("
          + repeatString("?", ", ", products.size()) + ") GROUP BY [rangeName]")) {
    int fieldNo = 1;  //NOPMD DU anomaly
    for (final DbProduct product: products) {
      statement.setInt(fieldNo++, product.getId());
    }
    try (ResultSet rset = statement.executeQuery()) {
      final String rangeName;
      if (rset.next()) {
        //Get the first range name
        rangeName = Nz.nz(rset.getString("rangeName"));
      } else {
        //There isn't one so return empty string
        rangeName = "";
      }
      if (rset.next()) {
        //But, if there are multiple ranges, this is an error so treat it as such
        throw new SQLException("The products you are trying to save exist already in the dabase under more than one range. "
            + "Cannot process the change");
      }
      return rangeName;
    }
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM