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

C#使用System.Data.SQLite读取SQLite字符串列返回科学计数法或类型错误问题

问题成因
  • SQLite本身是动态类型系统,采用类型亲和性机制而非强类型约束:即使你将Zakupki_name、Zakupki_description列声明为字符串类型,只要插入的内容是纯数字格式,SQLite会默认将其识别为INTEGER/REAL(浮点数)类型存储,而非TEXT类型。
  • 你当前使用字符串拼接的方式生成插入SQL,没有明确指定参数类型,进一步放大了SQLite的自动类型转换问题:超长的纯数字字符串超出SQLite INTEGER的存储上限时,会自动转成REAL浮点数存储,浮点数转字符串时默认就会输出科学计数法格式,且会丢失尾部精度。
  • 读取时抛出InvalidCast异常的原因是:底层存储的字段类型是浮点数而非字符串,直接调用GetString()属于不同类型的强转,不符合System.Data.SQLite的类型转换规则;调用GetValue().ToString()时,本质是对浮点数执行ToString操作,自然会得到科学计数法的结果。
修复方案

1. 优先替换插入逻辑为参数化查询(核心修复)

完全弃用字符串拼接SQL的方式,通过参数明确指定字段类型,强制SQLite将字符串内容按TEXT类型存储,同时还能避免SQL注入风险。修改后的插入代码示例:

public void InsertZakupku(string name, string description,double value_limit)
{
    try
    {
        createConnection();
        SQLiteCommand command = new SQLiteCommand(
            @"INSERT INTO Zakupki (
            Zakupki_name,
            Zakupki_description,
            Zakupki_update_date,
            Zakupki_value_limit
            ) VALUES (@name,@description,@updateDate,@valueLimit);"
        , connection); 
        // 明确指定参数类型为String,强制存为TEXT
        command.Parameters.Add("@name", System.Data.DbType.String).Value = name;
        command.Parameters.Add("@description", System.Data.DbType.String).Value = description;
        command.Parameters.Add("@updateDate", System.Data.DbType.String).Value = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
        command.Parameters.Add("@valueLimit", System.Data.DbType.Double).Value = value_limit;
        command.ExecuteNonQuery();
        closeConnection();
    }
    catch(Exception ex)
    {
        Console.WriteLine(ex.Message);
        closeConnection();
    }
}

2. 调整读取逻辑兼容已有数据

如果你的数据库中已经存在历史存储的浮点数格式数据,可以调整读取逻辑,避免异常同时输出非科学计数法的字符串:

while (reader.Read())
{
    // 读取字符串字段时先判断类型,兼容历史浮点存储的数据
    string name = reader.GetFieldType(1) == typeof(double) 
        ? ((decimal)reader.GetDouble(1)).ToString("F0") // 浮点数先转decimal再格式化输出,去掉小数点和科学计数法
        : reader.GetString(1);
    string description = reader.GetFieldType(2) == typeof(double) 
        ? ((decimal)reader.GetDouble(2)).ToString("F0")
        : reader.GetString(2);
    zakupkis.Add(new Zakupki(
        reader.GetInt32(0), 
        name, 
        description, 
        DateTime.Parse(reader.GetString(3)), 
        reader.GetDouble(4)
    ));
}

注意:如果历史数据超出double/decimal的精度范围,已经丢失的精度无法找回,建议从原始数据源重新导入数据。

3. 可选优化建表语句

如果还可以调整表结构,建表时明确将对应字段声明为TEXT类型,而非模糊的string,进一步强化SQLite的TEXT类型亲和性,减少自动类型转换的概率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 19:39:01