如何使用 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 子句
使用 Spark 执行“WHERE IN”子句,如何仅重新训练第一个数据集的列?
用户为 where in 子句提供的子查询是不是存在注入攻击?
SQL:如何在带有“NOT IN”条件的“Where”子句中使用“and”和“or”
带有 dapper 和 postgresql 的“WHERE x IN y”子句抛出 42601:在 \"$1\" 处或附近出现语法错误