1

自从 Android 中的 SQLite 开始以来,这个问题就一直困扰着我。选择参数是Strings. 什么?为什么?

让我们看看我的问题。我有一个正确填充的数据库:

sqlite> select count (*) from issues where project_id = 1;
3819

伟大的。让我们看一下代码:

public Cursor selectAllCursor(final long projectId) {
    final String selection = projectId > 0 ? KEY_PROJECT + " = ?" : null;
    final String[] selArgs = projectId > 0 ? new String[] {
        Long.toString(projectId)
    } : null;

    final Cursor c = mDb.query(TABLE_ISSUES, null, selection, selArgs, null, null, null);
    c.moveToFirst();
    return c;
}

嗯,返回Cursor的是空的。为什么?

sqlite> select count (*) from issues where project_id = '1';
0

嗯,这就是为什么。

我发现的唯一解决方法是:

public Cursor selectAllCursor(final long projectId) {
    final String selection = projectId > 0 ? KEY_PROJECT + " = " + projectId : null;
    final String[] selArgs = null;

    final Cursor c = mDb.query(TABLE_ISSUES, null, selection, selArgs, null, null, null);
    c.moveToFirst();
    return c;
}

它有效,但我觉得这很难看。
为什么选择参数不是数组Object而不是String?Android 框架会测试对象类型,如果它是整数 ( int/ long),它会告诉 SQLite 将其视为整数。

4

2 回答 2

1

参数对于避免字符串格式问题(包括 SQL 注入攻击)很有用。对于其他类型,您没有此类问题。

但这仍然意味着您必须根据值的类型使用完全不同的代码。此外,如果您使用compileStatement则可以使用其他类型作为参数,但SQLiteStatement仅适用于单个值 (1 x 1) 结果集。

这只是糟糕的 API 设计。

如果将表列声明为INTEGER,SQLite 的类型关联规则会自动将值转换回数字。但是,这仅适用于直接比较,例如Column = ?.

于 2013-02-18T17:02:20.497 回答
0

你是对的,文档很清楚参数将始终绑定为字符串。不知道为什么会这样(因为那是你的实际问题:-)),但找不到任何解决方法。

selectionArgs 您可以在选择中包含 ?s,它将被 selectionArgs 中的值替换,以便它们出现在选择中。这些值将绑定为字符串。

一种“更好”的做你所拥有的方式可能是使用String.format?例如

String selection = String.format("%s = %d", KEY_PROJECT, projectId )
于 2013-02-18T16:30:13.317 回答