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

SQLite存储加密货币高精度小数疑问:为何仅保留16位有效数字?

问题原因

SQLite是动态类型+类型亲和性的数据库,和SQL Server这类强类型数据库逻辑不同:

  • 你指定的DECIMAL、REAL、CURRENCY、MONEY等类型,默认会触发NUMERIC类型亲和性,但如果未启用SQLite的DECIMAL扩展,SQLite会将这类数值存储为REAL(即64位双精度浮点数)。
  • 双精度浮点数的有效数字仅为15-17位,你的输入123456789111.12345678有20位有效数字,超出了double的精度范围,因此会被四舍五入到16位有效数字存储。

解决方案

针对加密货币这类需要高精度的财务数据,有三种可靠的处理方式:

1. 用TEXT类型存储(最简便通用)

直接将数值以字符串形式存入TEXT列,完全保留精度,C#中可直接将decimal类型转字符串插入,读取时再转回decimal:

CREATE TABLE datas ( 
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    price TEXT NOT NULL
);

C#代码示例:

// 插入数据
using var cmd = connection.CreateCommand();
cmd.CommandText = "INSERT INTO datas (price) VALUES (@price)";
cmd.Parameters.AddWithValue("@price", yourDecimalValue.ToString(CultureInfo.InvariantCulture));
cmd.ExecuteNonQuery();

// 读取数据
using var cmd = connection.CreateCommand();
cmd.CommandText = "SELECT price FROM datas WHERE id = @id";
cmd.Parameters.AddWithValue("@id", 1);
var priceStr = cmd.ExecuteScalar() as string;
var price = decimal.Parse(priceStr, CultureInfo.InvariantCulture);

2. 启用SQLite的DECIMAL扩展(原生数值类型支持)

SQLite 3.38.0及以上版本支持原生DECIMAL类型,但需要编译时开启SQLITE_ENABLE_DECIMAL_EXTERNAL_SCHEMA选项。如果使用C#的Microsoft.Data.Sqlite或System.Data.SQLite库,部分预编译版本已包含该扩展:

  • 建表时明确指定高精度类型:
CREATE TABLE datas ( 
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    price DECIMAL(28,8) NOT NULL
);
  • C#中直接使用decimal参数插入,无需额外转换,库会自动处理高精度存储。

3. 拆分整数和小数部分(适合频繁数值计算场景)

将价格拆分为整数部分和小数部分(乘以10^8后转整数),用两个INTEGER列存储,彻底避免浮点精度问题:

CREATE TABLE datas ( 
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    price_int INTEGER NOT NULL, -- 整数部分
    price_frac INTEGER NOT NULL -- 小数部分*100000000
);

C#代码示例:

// 拆分decimal为整数和小数部分
var price = 123456789111.12345678m;
var priceInt = (long)Math.Truncate(price);
var priceFrac = (long)((price - priceInt) * 100000000);

// 插入
using var cmd = connection.CreateCommand();
cmd.CommandText = "INSERT INTO datas (price_int, price_frac) VALUES (@int, @frac)";
cmd.Parameters.AddWithValue("@int", priceInt);
cmd.Parameters.AddWithValue("@frac", priceFrac);
cmd.ExecuteNonQuery();

// 读取并组合
using var cmd = connection.CreateCommand();
cmd.CommandText = "SELECT price_int, price_frac FROM datas WHERE id = @id";
cmd.Parameters.AddWithValue("@id", 1);
using var reader = cmd.ExecuteReader();
if (reader.Read())
{
    var intPart = reader.GetInt64(0);
    var fracPart = reader.GetInt64(1);
    var totalPrice = intPart + (decimal)fracPart / 100000000;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 06:55:27