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
相关产品推荐
相关产品推荐

