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

如何创建可跨不同MySQL表查询的灵活函数?解决语法报错

问题描述

我正在尝试创建一个可以在MySQL中从不同表查询数据的函数。

我的函数代码如下:

async function getOne(table, table_parameter, parameter) {
  const result = await pool.query(
    `SELECT * FROM ? WHERE ? = ?`,
    [table, table_parameter, parameter]
  )
}

路由代码:

companiesRouter.get('/:id', async (request, response) => {
  const id = request.params.id
  const company = await getOne('Company', 'companyID', id)
  response.send(company)
})

运行后出现如下错误:

sql: "SELECT * FROM 'Company' WHERE 'companyID' = '1'",
sqlState: '42000',
sqlMessage: "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''Company' WHERE 'companyID' = '1'' at line 1"

请问有没有办法解决这个问题,让该函数正常工作?

解决方案

问题核心是参数化查询的误用:MySQL参数化查询仅会为数据值(比如1)添加引号,而表名、列名属于SQL标识符,不能用参数化方式处理——你的代码把Company(表名)和companyID(列名)当成了普通值,导致它们被自动套上单引号,直接违反SQL语法。

按以下步骤修复:

  1. 添加白名单校验:为防止SQL注入,必须先验证传入的表名、列名是否属于允许访问的范围,绝对不能直接把未校验的内容拼进SQL。
  2. 正确拼接标识符:对合法的表名、列名,用MySQL的反引号`包裹后拼入SQL(避免标识符含特殊字符时出错)。
  3. 补充结果返回逻辑:原函数没有返回查询结果,需要补上返回语句。

修改后的函数代码示例:

// 定义允许访问的表及对应列的白名单
const allowedTables = {
  Company: ['companyID', 'name', /* 这里可以添加该表其他允许查询的列 */]
};

async function getOne(table, table_parameter, parameter) {
  // 校验表名是否合法
  if (!allowedTables[table]) {
    throw new Error('禁止访问该表');
  }
  // 校验列名是否合法
  if (!allowedTables[table].includes(table_parameter)) {
    throw new Error('禁止访问该列');
  }
  // 拼接合法标识符,仅对参数值使用参数化查询
  const result = await pool.query(
    `SELECT * FROM \`${table}\` WHERE \`${table_parameter}\` = ?`,
    [parameter]
  );
  // 返回查询结果(根据你的数据库库返回格式调整,比如取result[0])
  return result[0];
}

路由代码无需修改,白名单校验已经规避了SQL注入风险。

额外注意:

  • 永远不要跳过白名单校验直接拼接表名/列名,这会导致严重的SQL注入漏洞。
  • MySQL中标识符(表名、列名)必须用反引号`包裹,单引号仅用于字符串值。

内容的提问来源于stack exchange,提问作者Aleksei Yin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 16:57:38