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

Discord Bot存储BigInt类型用户ID后查询结果异常求助

问题原因与解决方案

这个问题我太熟悉了——本质是JavaScript的Number类型精度限制,加上MySQL驱动的默认处理逻辑,才导致查询回来的Discord ID末尾多了两个0。

为啥会出现这个情况?

Discord的用户ID是64位的Snowflake ID,这个数值早就超过了JavaScript里Number类型的最大安全整数(也就是9007199254740991)。当你的MySQL驱动从数据库读取BIGINT类型的ID时,默认会把它转成Number类型,而超出安全范围的数值会被自动近似处理,这种近似就可能表现为末尾多出两个0(不同数值的近似结果可能不一样,但都是精度丢失的表现)。

你在数据库里看到ID是对的,那是因为数据存在库里是完整的,但一旦被读到Node.js环境里,就已经被转成了不精确的Number,之后的JSON.stringify和JSON.parse只是把这个错误的数值固化下来,最后发给你的自然就是错的ID。

怎么解决?

给你几个靠谱的方案,按推荐程度排序:

1. 修改MySQL连接配置,强制返回字符串

在创建数据库连接的时候,加上supportBigNumbers: true和bigNumberStrings: true这两个配置,这样驱动就会把BIGINT类型的数据直接以字符串形式返回,完全避免精度丢失:

const con2 = mysql.createConnection({
  host: '你的主机地址',
  user: '数据库用户名',
  password: '数据库密码',
  database: '你的库名',
  supportBigNumbers: true,
  bigNumberStrings: true
});

这样处理后,你拿到的discord_id就是原原本本的字符串ID,序列化反序列化都不会出问题。

2. 把数据库字段改成VARCHAR类型

其实Discord ID根本不需要做数值计算,本质就是一串字符串。直接把discord_id字段改成VARCHAR(20)(Snowflake ID最长也就18位左右,20位完全够),从存储到读取全程用字符串处理,彻底绕开数值类型的坑。

3. 手动把查询结果里的BigInt转成字符串(临时方案)

如果不想改配置或数据库结构,可以在拿到查询结果后,先把ID转成字符串再序列化:

con2.query(`SELECT * FROM discord_user WHERE discord_id = '${id}'`, (err, result, fields) => {
  if (err) throw err;
  // 先把BigInt转成字符串
  result[0].discord_id = result[0].discord_id.toString();
  const string = JSON.stringify(result);
  const json = JSON.parse(string);
  message.author.send(json[0].discord_id);
});

不过这个方法只适合单个字段的场景,要是有多个BigInt字段,处理起来就很麻烦,不如前两种彻底。

额外提个醒

你的代码里直接把id拼进SQL语句里,这可是SQL注入的高危操作!赶紧改成参数化查询:

con2.query('SELECT * FROM discord_user WHERE discord_id = ?', [id], (err, result, fields) => {
  // 后续逻辑不变
});

这样能有效防止恶意注入,代码安全多了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 03:44:18