4

(如果您能想到更好的方法,请随时改进问题标题。)

问题:考虑以下 SQLite 查询:

SELECT COUNT(*)
  FROM (SELECT 1 AS value UNION SELECT 2 AS value)
 WHERE value <= ?

当我1用作参数时,我希望查询 yield 1,但它 yield 2。为什么会这样?


附加信息

这是重现问题的最小工作示例(Android):

Cursor c = db.rawQuery(
        "SELECT COUNT(*) " +
        "  FROM (SELECT 1 AS value UNION SELECT 2 AS value) " +
        " WHERE value <= ? ",
        new String[] {String.valueOf(1)});

c.moveToFirst();
Log.i("", "Result: " + String.valueOf(c.getInt(0)));

可能与参数作为字符串传递的事实有关,但是,唉,没有其他方法可以将参数传递给 SQLite API,所以我想我在这里没有做任何“错误”,它是 SQLite 的工作以适当地转换值。在使用查询的非参数化版本时,我还观察到以下情况(这可能与问题相关,也可能不相关):

SELECT COUNT(*)
  FROM (SELECT 1 AS value UNION SELECT 2 AS value)
 WHERE value <= 1              -- yields 1

SELECT COUNT(*)
  FROM (SELECT 1 AS value UNION SELECT 2 AS value)
 WHERE value <= '1'            -- yields 2
4

1 回答 1

5

文档中说rawQuery

[...] 您可以在查询的 where 子句中包含 ?s,它将被 selectionArgs 中的值替换。这些值将绑定为字符串。

并且,引用SQLite 文档

根据以下规则,比较的结果取决于操作数的存储类别 [...]

  • INTEGER 或 REAL 值小于任何 TEXT 或 BLOB 值。

由于 1 和 2都是整数,因此它们都小于“1”(TEXT 值)。这就是为什么这个声明:

SELECT 2 <= '1'

... 在 SQLite 中返回 1。

您可能应该使用...

WHERE value <= CAST('1' AS INTEGER)

... 反而。或者您可以使用所有数学运算符将两个操作数都转换为带有 NUMERIC 存储类的事实WHERE value <= + ?,但这不太干净,imo。

请注意,在此查询中:

SELECT * FROM myTable WHERE _id < ?

...的值?将使其亲和力调整为_id 的亲和力- 因此它们将作为数字进行比较,如果_id是 NUMERIC。

于 2012-11-12T16:40:24.180 回答