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

非西语区域设置下SQLiteDatabase整数查询崩溃问题解决咨询

问题根源

你遇到的这个崩溃完全是MessageFormat的区域特性搞的鬼:在阿拉伯语这类非西语区域设备上,它会把数字1自动转换成当地的阿拉伯-Indic数字١。而SQLite根本不认识这种本地化数字,它会把١当成一个列名来解析,自然就抛出"no such column"的错误了。

解决方案

下面给你几个靠谱的解决办法,按推荐程度排序:

1. 用SQLite参数化查询(强烈推荐)

这是最安全也最规范的做法,不仅能彻底解决区域本地化问题,还能防止SQL注入攻击。把你的代码改成用?作为占位符,而不是自己拼接SQL:

// 把查询语句改成用?作为参数占位符
private static final String JUMP_COUNT_QUERY = 
    "select count(*) " + 
    "from log_entry " + 
    "inner join log_entry_rig on log_entry._id = log_entry_rig.log_entry " + 
    "where log_entry_rig.rig = ?";

// 执行查询时把参数传给rawQuery的第二个参数
Cursor cursor = null;
try {
    cursor = db.rawQuery(JUMP_COUNT_QUERY, new String[]{String.valueOf(rigId)});
    // 后续逻辑...
} finally {
    // 别忘了关闭cursor
    if (cursor != null) {
        cursor.close();
    }
}

这样SQLite会自己处理参数的格式化,完全不受系统区域设置影响,而且从根本上避免了SQL注入的风险,这是Android操作SQLite的标准做法。

2. 指定MessageFormat使用中立区域

如果你因为某些原因必须继续使用MessageFormat,那可以强制它使用Locale.ROOT或者Locale.US来格式化,这样数字就会保持ASCII的0-9格式:

// 创建MessageFormat时指定中立区域
MessageFormat format = new MessageFormat(JUMP_COUNT_QUERY_FORMAT, Locale.ROOT);
String query = format.format(new Object[]{rigId});
Cursor cursor = null;
try {
    cursor = db.rawQuery(query, null);
    // 后续逻辑...
} finally {
    if (cursor != null) {
        cursor.close();
    }
}

不过这种方法还是存在SQL注入的风险,所以只推荐在没办法用参数化查询的场景下临时用。

3. 手动把本地化数字转成ASCII数字

还有一种笨办法,就是把rigId转换成字符串后,替换掉所有非ASCII的数字字符。比如写一个工具方法:

private static String convertToAsciiNumber(String localizedNumber) {
    StringBuilder sb = new StringBuilder();
    for (char c : localizedNumber.toCharArray()) {
        if (Character.isDigit(c)) {
            // 把本地化数字转成ASCII数字
            sb.append(Character.getNumericValue(c));
        } else {
            sb.append(c);
        }
    }
    return sb.toString();
}

// 使用时
String query = MessageFormat.format(JUMP_COUNT_QUERY_FORMAT, convertToAsciiNumber(String.valueOf(rigId)));

这种方法比较繁琐,而且容易遗漏某些特殊区域的数字格式,所以不推荐作为首选方案。

总结

优先选择参数化查询,这是行业标准的最佳实践,既能解决当前的崩溃问题,又能提升代码的安全性。如果实在要用字符串拼接的方式,再考虑指定MessageFormat的区域。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:02:33