HarmonyOS鸿蒙Next中记录一下关系数据库中存取long/int64 类型的数据碰到的问题
HarmonyOS鸿蒙Next中记录一下关系数据库中存取long/int64 类型的数据碰到的问题
1. 使用number类型会导致精度丢失
服务器返回的数据是这样的:
{ "id":112233445566778899 }
用number来接收结果会导致精度丢失,打印出来的值变成了112233445566778900
2. 数据库中使用bigint类型或者string类型
如果只是存取用bigint没问题,那如果对这个字段进行比较、排序等谓词操作就不行了,因为bigint不支持

那用数据库TEXT类型呢?它支持比较、排序等谓词操作

name字段是TEXT类型 ORDER BY NAME ASC, NAME按照升序排序就会出现如图结果。
2比112233445566778899大,是因为SQLite 会按照字典顺序逐个字符进行比较,第一个字符 ‘2’ 的编码大于第一个字符 ‘1’ 的编码,比较即停止。而不是把字符串转换为数字再进行比较,所以会出现2比112233445566778899大。
3. 那有什么方式能保证数据精度不丢失,也支持按照它真实的值进行比较、排序等谓词操作
答案是有的,数据库用INTEGER类型,因为sqlite3的INTEGER类型是64位有符号位整数完美匹配long/int64类型
//建表
CREATE TABLE IF NOT EXISTS USER (ID INTEGER, NAME TEXT NOT NULL)
如图:ORDER BY USER.ID ASC,按照id升序排序

那问题又绕回来了number类型会导致精度丢失,那要怎么防止精度丢失?
方案一:arkts代码中不要用number类型,用bigint或string拼接成SQL语句进行增删改查
@Local insertValue: string = '112233445566778899'
//插入
this.rdbStore?.executeSql(`INSERT INTO USER (ID, NAME) VALUES (${this.insertValue}, '${this.insertValue}' )`)
//查询
let resultSet = this.rdbStore?.querySqlSync(`select * from user where id >= ${this.insertValue};`)
方案二:arkts代码里面用string类型,用RdbPredicates处理谓词,就用官方rdbStore提供的api来进行增删改查
@Local insertValue: string = '112233445566778899'
//插入
const row: relationalStore.ValuesBucket = {
'id': this.insertValue,
'name': this.insertValue
};
let insertNum = await this.rdbStore?.insert('USER', row)
//查询
let predicates = new relationalStore.RdbPredicates('USER')
predicates.greaterThanOrEqualTo('id', this.insertValue)
let resultSet = this.rdbStore?.querySync(predicates, ['ID', 'NAME'])
最后是关于取值的问题,这个字段千万不要用getValue,要用getString

resultSet.getString(resultSet.getColumnIndex('ID'))//这里打印的是112233445566778899,没有丢失精度
resultSet.getValue(resultSet.getColumnIndex('ID')) //这里打印的是112233445566778900,丢失了精度
更多关于HarmonyOS鸿蒙Next中记录一下关系数据库中存取long/int64 类型的数据碰到的问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html
是的,一般decimal或者number不同数据库都是用来存精确数字的,或者string再转换。
更多关于HarmonyOS鸿蒙Next中记录一下关系数据库中存取long/int64 类型的数据碰到的问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
上文的有两个图片来自HarmonyOS Debug Database这个库,开发调试非常好用。
感谢,学到了
在HarmonyOS Next中,关系数据库(RDB)存储long/int64类型数据时,需注意数据类型映射。使用@ColumnInfo注解时,确保字段类型为long,数据库列类型为INTEGER。插入数据时,通过ValuesBucket以Long对象形式放入。查询时,使用ResultSet的getLong方法获取。避免直接使用int或Integer,可能导致精度丢失或类型不匹配。
在HarmonyOS Next中处理大整数(long/int64)时,你总结的方案是正确的。核心是避免使用ArkTS的number类型(双精度浮点数)直接存储和传输,因为其精度有限。
关键点:
- 数据库字段类型:应使用
INTEGER(SQLite的64位有符号整数),而非BIGINT(ArkTS RDB谓词不支持)或TEXT(字符串比较不符合数值语义)。 - 应用层数据类型:在ArkTS代码中,使用
string类型来承载大整数的值,以保持精度。 - API选择:
- 插入/更新:使用
rdbStore.insert()、update()等方法,通过ValuesBucket传入string类型的值。 - 查询:使用
RdbPredicates构建查询条件(如greaterThanOrEqualTo),条件值传入string。 - 读取:从
ResultSet中必须使用getString()方法获取该字段值,切勿使用getValue()(其返回number会导致精度丢失)。
- 插入/更新:使用
- 备选方案:直接拼接SQL语句执行(
executeSql,querySqlSync),此时参数也需用string类型嵌入。
你的两种方案(直接执行SQL或使用RDB谓词API)都是可行的,后者更符合HarmonyOS RDB的推荐用法。这确保了从服务器接收、存储、条件过滤到最终读取的全流程精度无损。

