You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 17:05:25