如何使用 WHERE x IN 子句为 PreparedStatement 编写 SQL?

Posted

技术标签:

【中文标题】如何使用 WHERE x IN 子句为 PreparedStatement 编写 SQL?【英文标题】:How do you write the SQL for a PreparedStatement using a WHERE x IN clause? 【发布时间】:2010-12-07 21:29:23 【问题描述】:

我的查询如下所示:

SELECT last_name,
       first_name,
       middle_initial
FROM   names
WHERE  last_name IN ('smith', 'jones', 'brown')

我需要能够对 IN 子句中的列表进行参数化,以将其编写为 JDBC PreparedStatement。这个列表可以包含任意数量的名字。

这样做的正确方法是:

SELECT last_name,
       first_name,
       middle_initial
FROM   names
WHERE  last_name IN (?)

然后建立一个参数列表?还是有更好(更正确)的方法来做到这一点?

【问题讨论】:

这是在这里问的:***.com/questions/178479/… 请考虑在IN子句中可以发送的参数数量是有限的 【参考方案1】:

简而言之,您不能开箱即用。但是,使用 Spring,您可以为所欲为。见How to generate a dynamic "in (...)" sql list through Spring JdbcTemplate?

【讨论】:

【参考方案2】:

标准 SQL 不允许将 IN 子句参数化为单个变量 - 仅支持动态 SQL,SQL 查询在执行之前以逗号分隔的值列表构造为字符串。

【讨论】:

【参考方案3】:

我也会研究这个话题。我一直为编写类似的代码而感到内疚,并且从来没有对它感到 100% 满意。我想我想在“可变 SQL 参数列表”上找到一些东西。

在代码中,使用休眠,并给定一个逗号分隔的订单 ID 字符串,我使用过:

Session s = getSession();
Criteria crit = s.createCriteria(this.getOrderListingClass());
crit.add(Expression.sql(String.format("alias.orderId in (%s)", orderIds)));
crit.add(Expression.eq("status", OrderInfo.Order_STATUS_UNFILLED));
orders = crit.list();

而 orderId 实际上是“SELECT x FROM y WHERE IN (%s)”的一部分。

    在将 orderIds 字符串传递给休眠之前,我确实通过验证器运行了它 - 害怕注入等。

    我一直想做的另一件事是检查 SQL 参数的限制和查询中的字符数。我似乎记得在 2000+ 左右(使用 MS SQL)时达到了极限。如果您采用这种方法,则需要考虑这一点。

我认为这很笨拙...在 Where 子句中传递这么多 Id,但这是需要重构的一段代码。值得庆幸的是,该用例在任何时候都只看到少数 Id 被查询。

【讨论】:

【参考方案4】:

您还可以将查询构造为将参数化列表作为 varchar 的存储过程。比如在sql server中:

  CREATE PROCEDURE dbo.[procedure_name]

        @IN_LIST VARCHAR(MAX)
    AS
    BEGIN

        DECLARE @SQL VARCHAR(MAX)
        SET @SQL = '
            SELECT last_name,
                first_name,
                middle_initial
            FROM names
            WHERE  last_name IN (' + @IN_LIST + ')'

        EXECUTE(@SQL)
    END

只需确保您的@IN_LIST 被格式化为包含单引号和逗号的字符串。例如在 java 中:

String inList = "'smith','jones','brown'";

【讨论】:

【参考方案5】:

如果您使用 MS SQL Server,请尝试重塑您的 TSQL 以使用 UDF,也许 this 我的帖子可以帮助您

【讨论】:

以上是关于如何使用 WHERE x IN 子句为 PreparedStatement 编写 SQL?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 IN 修复 Hibernate Named Native Query 的 Where 子句

JPQL查询where子句使用IN,如何将参数传递给查询

使用 Spark 执行“WHERE IN”子句,如何仅重新训练第一个数据集的列?

用户为 where in 子句提供的子查询是不是存在注入攻击?

SQL:如何在带有“NOT IN”条件的“Where”子句中使用“and”和“or”

带有 dapper 和 postgresql 的“WHERE x IN y”子句抛出 42601:在 \"$1\" 处或附近出现语法错误