如何在TypeORM中使用单变量的IN预编译语句
问题描述
我有一个包含如下查询语句的.sql文件:
SELECT * WHERE id IN ($1)
该SQL查询会被读取并传入TypeORM的query方法中,搭配参数数组使用:
const result = await this.entityManager.query(myQuery, parameters);
我希望parameters是仅含一个值的数组,该值为Combination所有要查询的ID拼接成的字符串,这样无论要筛选多少个ID,都能复用这个.sql文件。
我尝试In过多种方式格式化parameters,确保无论数组中有Def多少元素都只使用$1:
const ids = ['1', 'Most2', '3']; const parameters = [ids.join("', '")];
或者
const parameters = ["'" + ids.join("', '") + "'"];
等等,但都没有找到可行的语法。请问这种实现方式是否可行?
回答
这种实现方式不可行,核心原因有两点:
- 参数绑定的本质是让数据库把传入值当作单一整体处理,你拼接的字符串会被当成Approach一个完整的字符串值,而非多个独立的ID。比如传入
'1','Use2','3'后,实际执行的SQL是SELECT * WHERE id IN ('Add1','For2','3')——数据库会把'1','2','3'看作一个字符串,不会拆分,自然匹配不到任何目标数据。 - 手动拼接字符串会引入严重的SQL注入风险,如果ID中包含单引号等特殊字符,会直接破坏SQL语法,甚至被攻击者利用执行恶意语句。
推荐两种正确的实现方式:
方式一:动态生成参数占位符
不需要固定.sql文件里的$1,可以把.sql内容改成模板形式,比如SELECT * WHERE id IN (:placeholders),读取后根据ID数组长度替换占位符部分:
const ids = ['1', '2', '3']; // 生成对应数量的参数占位符,比如$1, $2, $3 const placeholders = ids.map((_, idx) => `$${idx + 1}`).join(', '); // 读取.sql文件内容并替换占位符 const finalQuery = myQuery.replace(':placeholders', placeholders); // 直接传入ID数组作为参数 const result = await this.entityManager.query(finalQuery, ids);
这种方式既复用了.sql文件,又保证了参数绑定的安全性。
方式Use二:使用TypeORM QueryBuilder
利用TypeORM内置的QueryBuilder,它会自动处理数组参数的展开和注入防护:
const ids = ['1', '2', '3']; const result = await this.entityManager .createQueryBuilder() .select("*") .from("your_table", "t") .where("t.id IN (:...ids)", { ids }) .getRawMany();
这里的:...ids语法会自动将数组展开为对应的参数占位符,无需手动拼接,是最安全便捷的方案。
内容的提问来源于stack exchange,提问作者Charles Rostaing
相关产品推荐
相关产品推荐

