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

PostgreSQL+Node.js分页查询报错:$1与$2附近存在语法问题

问题原因

参数化查询的占位符($1、$2)不能用来指定排序字段(ORDER BY后的列名)和排序方向——数据库会把这些参数解析成字符串字面量,最终生成的SQL会变成:

SELECT * FROM users ORDER BY 'user_id' 'DESC' LIMIT ...

这种写法完全不符合SQL语法,自然会触发报错。

解决方法

排序字段和方向需要动态拼接到SQL中,但必须先做合法性校验(防止SQL注入);Limit和Offset可以继续用参数化查询,因为它们是数值类型,不存在注入风险。

修改后的完整代码

const getPagination = (page, size) => {
    const limit = size ? +size : 4;
    const offset = page ? page * limit : 0;
    return { limit, offset };
};

const getUsers = async (req, res) => {
    // 定义允许排序的字段列表,锁定合法列,防止SQL注入
    const allowedOrderFields = ['user_id', 'username', 'email']; // 按你的users表实际字段调整
    let orderby = req.query.orderby;
    // 校验排序字段,不合法则用默认值
    if (!allowedOrderFields.includes(orderby)) {
        orderby = 'user_id';
    }

    let orderDir = req.query.orderDir?.toUpperCase();
    // 校验排序方向,只能是ASC或DESC
    if (!['ASC', 'DESC'].includes(orderDir)) {
        orderDir = 'DESC';
    }

    const { page, size } = req.query;
    const { limit, offset } = getPagination(page, size);
    
    // 动态拼接合法的排序规则,Limit和Offset保留参数化
    const query = `SELECT * FROM users ORDER BY ${orderby} ${orderDir} LIMIT $1 OFFSET $2`;
    
    try {
        const data = await db.query(query, [limit, offset]);
        console.log(data);
        res.json(data.rows);
    } catch (err) {
        res.status(500).send({
            message: err.message || '查询用户时发生错误'
        });
    }
};
关键细节
  • 合法性校验是核心:必须限制排序字段只能是预设的列名,彻底避免攻击者传入恶意字符串触发SQL注入。
  • 排序方向统一大写:强制转成大写格式,避免传入小写的asc/desc导致语法问题。
  • 统一async/await写法:原代码混用await和.then(),改成try/catch更符合异步代码的规范,可读性更强。

内容的提问来源于stack exchange,提问作者Rajiv Ranjan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 05:35:13