使用node-postgres执行带IN子句SELECT查询的正确方法
你当前的写法是错误的。
你将拼接好的带单引号的字符串作为单个参数传入,node-postgres会把整个inList识别为单个字符串值进行转义,最终执行的SQL实际等价于SELECT name FROM my_table WHERE info IN ('''qwerty'', ''qaz'''),完全不符合你的预期,还可能存在SQL注入风险。
以下是两种合规的实现方案:
方案1:使用PostgreSQL的ANY语法(推荐)
这是node-postgres官方推荐的数组参数匹配方案,写法最简单,不需要动态拼接占位符:
async function getUser() { // 直接定义要查询的取值数组,不需要手动加单引号和逗号 const inList = ['qwerty', 'qaz']; // 用=ANY($1)接收数组参数 const result = await pgPool.query("SELECT name FROM my_table WHERE info = ANY($1)", [inList]); if (result.rowCount >= 1) return result.rows.map(row => row.name); return false; }
注意:你原代码里判断rowCount == 1的逻辑不符合IN子句的特性,IN会匹配多条结果,建议改成>=1更符合预期
方案2:动态生成IN子句的占位符
如果坚持要使用IN语法,可以根据数组长度动态生成对应数量的参数占位符:
async function getUser() { const inList = ['qwerty', 'qaz']; // 生成对应数量的占位符:$1,$2 const placeholders = inList.map((_, index) => `$${index + 1}`).join(','); const result = await pgPool.query( `SELECT name FROM my_table WHERE info IN (${placeholders})`, inList ); if (result.rowCount >= 1) return result.rows.map(row => row.name); return false; }
两种方案都是参数化查询,不会有SQL注入风险,优先推荐方案1。
内容的提问来源于stack exchange,提问作者ArthurJ
相关产品推荐
相关产品推荐

