如何在Slonik中生成多列动态ORDER BY查询
解决Slonik中动态多列ORDER BY子句的问题
Slonik默认会把模板字符串中的变量当作参数值绑定,而非直接拼接SQL语句,所以你直接插入字符串变量会被转义成占位符,导致SQL语法错误。下面是两种可行的解决方法:
方法1:直接构建SQL片段(需确保输入可信)
如果能确认用户提供的排序参数是安全可信的(比如内部系统使用,或已做严格校验),可以使用sql.raw()创建SQL片段:
import { sql } from 'slonik'; // 模拟用户传入的排序规则 const sortRules = [ { column: 'created_at', direction: 'ASC' }, { column: 'updated_at', direction: 'DESC' } ]; // 生成ORDER BY子句 const orderByClause = sql.raw( `ORDER BY ${sortRules.map(rule => `${rule.column} ${rule.direction}`).join(', ')}` ); // 拼接最终查询 const query = sql` SELECT * FROM user WHERE gender = 'male' ${orderByClause} LIMIT 10 OFFSET 0; `;
方法2:安全构建(防SQL注入)
如果用户输入不可信,必须通过白名单验证+Slonik的安全API来构建排序子句,避免注入风险:
import { sql } from 'slonik'; // 定义允许排序的列和方向白名单 const allowedColumns = ['created_at', 'updated_at', 'username']; const allowedDirections = ['ASC', 'DESC']; // 模拟用户提交的排序参数 const userSortInput = [ { column: 'created_at', direction: 'ASC' }, { column: 'updated_at', direction: 'DESC' } ]; // 验证并生成排序片段 const sortSegments = userSortInput.map(({ column, direction }) => { // 校验列名是否合法 if (!allowedColumns.includes(column)) { throw new Error(`非法排序列:${column}`); } // 校验排序方向,默认用ASC const validDirection = allowedDirections.includes(direction.toUpperCase()) ? direction.toUpperCase() : 'ASC'; // 用sql.identifier转义列名,防止注入 return sql`${sql.identifier([column])} ${validDirection}`; }); // 拼接成完整的ORDER BY子句(无参数时留空) const orderByClause = sortSegments.length ? sql`ORDER BY ${sql.join(sortSegments, sql`, `)}` : sql``; // 最终查询语句 const query = sql` SELECT * FROM user WHERE gender = 'male' ${orderByClause} LIMIT 10 OFFSET 0; `;
关键说明
sql.identifier()会自动转义列名,避免因恶意输入导致的SQL注入- 白名单验证确保只有预设的列和排序方向能被使用,进一步提升安全性
- Slonik的
sql.join()可以安全地将多个SQL片段用指定分隔符拼接
内容的提问来源于stack exchange,提问作者Md. Sajedul Karim
相关产品推荐
相关产品推荐

