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

使用mysql2查询MySQL JSON数组中匹配名称的宝可梦对象

核心问题说明

你当前的写入逻辑存在缺陷:调用JSON_ARRAY_APPEND时传入了JSON.stringify(pokemon)生成的字符串,导致pokemons JSON数组中存储的是转义后的JSON字符串,而非结构化的嵌套JSON对象,这是直接使用JSON查询函数无法匹配到结果的根本原因。

第一步:修正写入逻辑

写入时不要手动序列化宝可梦对象,直接通过参数化查询传入JS对象,mysql2会自动处理JSON类型转换,同时彻底避免SQL注入和转义错误:

await con.query(
  `UPDATE profileSchema SET pokemons = JSON_ARRAY_APPEND(pokemons, '$', ?) WHERE id = ?`,
  [pokemon, interaction.user.id]
);

如果库中已经存在历史的字符串格式数据,可以执行以下一次性SQL完成修复:

UPDATE profileSchema
SET pokemons = (
  SELECT JSON_ARRAYAGG(JSON_EXTRACT(item, '$'))
  FROM JSON_TABLE(pokemons, '$[*]' COLUMNS(item JSON PATH '$')) t
);
第二步:实现按名称查询宝可梦

MySQL 8.0+ 推荐方案(直接返回匹配对象)

使用JSON_TABLE将JSON数组拆为临时表结构,直接匹配名称返回对应的宝可梦对象,SQL如下:

SELECT p.pokemon_data
FROM profileSchema,
JSON_TABLE(
  pokemons,
  '$[*]' COLUMNS (
    pokemon_data JSON PATH '$',
    pokemon_name VARCHAR(100) PATH '$.name'
  )
) p
WHERE id = ? AND p.pokemon_name = ?
LIMIT 1;

对应的Node.js调用代码:

const [result] = await con.query(
  `SELECT p.pokemon_data
  FROM profileSchema,
  JSON_TABLE(
    pokemons,
    '$[*]' COLUMNS (
      pokemon_data JSON PATH '$',
      pokemon_name VARCHAR(100) PATH '$.name'
    )
  ) p
  WHERE id = ? AND p.pokemon_name = ?
  LIMIT 1`,
  [targetUserId, targetPokemonName]
);
// result[0].pokemon_data 即为匹配到的宝可梦对象,mysql2会自动解析为JS可直接使用的对象

如果存在同名宝可梦需要全部返回,去掉SQL末尾的LIMIT 1即可。

MySQL 5.7 兼容方案

如果你的MySQL版本低于8.0不支持JSON_TABLE函数,可以先查询出对应用户的整段pokemons数组,在代码层做过滤:

const [result] = await con.query(
  `SELECT pokemons FROM profileSchema WHERE id = ?`,
  [targetUserId]
);
const targetPokemon = result.length ? result[0].pokemons.find(p => p.name === targetPokemonName) : null;
注意事项
  • 禁止使用字符串拼接的方式生成SQL语句,必须使用?占位符的参数化查询,否则存在SQL注入风险,特殊字符也会导致语句执行报错
  • JSON类型字段中要存储结构化的JSON值,不要存储序列化后的字符串,否则所有JSON查询函数都无法正常工作

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 14:30:41