2012-11-12 229 views
4

(隨意提高問題的標題,如果你能想到的更好的東西。)奇怪的行爲

問題:考慮以下SQLite的查詢:

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

當我使用1作爲參數,I 預計查詢產生1,但它產生2。爲什麼會發生?


信息

這是一個最小的工作示例重現該問題(安卓):

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的工作,轉換值a​​p propriately。我還觀察到使用查詢的非參數化的版本(這可能是也可能不是相關的問題)時,以下幾點:

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 
+0

是有意義的。 char'1'= 49 – njzk2

+0

也許你可以使用SELECT'1'和SELECT'2' – njzk2

回答

5

這是rawQuery文檔中說:

[...]你可以在查詢中的where子句中包含?,它將被來自selectionArgs的值替換。 這些值將被綁定爲字符串。

而且,引述SQLite doc

一個比較的結果取決於 操作數的存儲類,根據下面的規則[...]

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

由於兩個圖1和2是整數,他們比 '1'(TEXT值)都小。這就是爲什麼這個聲明:

SELECT 2 <= '1' 

...在SQLite中返回1。

你或許應該使用...

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

...相反。或者您可以使用這樣一個事實,即所有數學運算符都將這兩個操作數與WHERE value <= + ?一起投入NUMERIC存儲類,但這不太乾淨。

注意,在此查詢:

SELECT * FROM myTable WHERE _id < ? 

... the value of ? will get its affinity adjusted to the affinity of _idcolumn - 因此,他們將作爲數字相比,如果_id是數字。

+1

就是這樣,謝謝!因此,只有在將它們直接與數據庫列進行比較時,才能對參數進行自動類型調整......這很好理解。 – Heinzi