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

TypeScript中SQLite3存储Discord ID的精度问题及解决

问题:Discord ID查询时末尾数字精度丢失(SQLite3 + TypeScript)

我用TypeScript开发Discord机器人,采用SQLite3作为数据库。执行SELECT * FROM Users;查询Users表时,遇到Discord ID末尾3位数字被替换的异常:实际存储的Discord ID为1248626823638552701,但查询返回的却是1248626823638552600。

Users表结构

CREATE TABLE IF NOT EXISTS Users (
    _id INTEGER PRIMARY KEY AUTOINCREMENT,
    id TEXT NOT NULL UNIQUE,         -- Discord ID存储为TEXT类型
    xp INTEGER DEFAULT 0,
    level INTEGER DEFAULT 0,
    balance REAL DEFAULT 0.00,
    market_items TEXT DEFAULT NULL,  -- 物品ID的JSON数组
    last_level_up TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

我已经将存储Discord ID的id字段设为TEXT类型,目的就是避免大数字的整数溢出问题。数据库中存储的ID是正确的,但精度丢失出现在数据检索阶段。

已尝试的排查步骤

  • 数据类型验证:确认Users表的id字段确实为TEXT类型
  • 直接检查数据库:通过SQLite浏览器验证存储的ID完全正确
  • 控制台日志:在TypeScript代码中添加日志,确认检索到的ID确实存在末尾数字错误
  • 类型转换:尝试将检索到的ID转为BigInt类型
  • 更新依赖:确保使用最新版本的sqlite3库
  • 更换查询方式:尝试参数化查询、以数组格式获取数据等

问题解决

最终确认问题根源是未正确将检索到的ID转换为字符串类型。

原因是:JavaScript的Number类型最大安全整数为2^53-1(即9007199254740991),而Discord ID是18位数字,远超过这个阈值。sqlite3驱动默认会将TEXT类型的大数字尝试解析为Number类型,导致精度丢失。

修正方案

在读取数据库返回的结果时,强制将id字段转为字符串:

db.all('SELECT * FROM Users;', (err, rows) => {
  if (err) throw err;
  rows.forEach(row => {
    // 强制转为字符串,避免Number类型的精度丢失
    const discordId = String(row.id);
    console.log(discordId); // 输出正确的Discord ID
  });
});

若需要全局配置避免此类问题,也可以在初始化sqlite3连接时指定mode: 'string',让所有字段都以字符串形式读取:

const db = new sqlite3.Database('./your-db.db', { mode: sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE }, (err) => {
  if (err) console.error(err.message);
});
db.configure('mode', 'string');

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 21:19:51