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

5 回复

是的,一般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类型(双精度浮点数)直接存储和传输,因为其精度有限。

关键点:

  1. 数据库字段类型:应使用INTEGER(SQLite的64位有符号整数),而非BIGINT(ArkTS RDB谓词不支持)或TEXT(字符串比较不符合数值语义)。
  2. 应用层数据类型:在ArkTS代码中,使用string类型来承载大整数的值,以保持精度。
  3. API选择
    • 插入/更新:使用rdbStore.insert()update()等方法,通过ValuesBucket传入string类型的值。
    • 查询:使用RdbPredicates构建查询条件(如greaterThanOrEqualTo),条件值传入string
    • 读取:从ResultSet中必须使用getString()方法获取该字段值,切勿使用getValue()(其返回number会导致精度丢失)。
  4. 备选方案:直接拼接SQL语句执行(executeSql, querySqlSync),此时参数也需用string类型嵌入。

你的两种方案(直接执行SQL或使用RDB谓词API)都是可行的,后者更符合HarmonyOS RDB的推荐用法。这确保了从服务器接收、存储、条件过滤到最终读取的全流程精度无损。

回到顶部