2013-08-02 58 views
6

我想選擇數據庫中的一些數據,我有兩個代碼片做:selectionArgs兩個在SQLiteQueryBuilder不整數值列工作

cursor = builder.query(db, 
        new String[]{"col1", "col2", "col3"}, 
        "id = ?", new String[]{getSID(db)}, null, null, null); 

cursor = builder.query(db, 
        new String[]{"col1", "col2", "col3"}, 
        "id = " + getSID(db), null, null, null, null); 

它們之間的區別在於,根據文檔,第一個似乎更正確,但它也不起作用 - 遊標是空的。而不是第二個 - 我得到我需要的所有數據。

於是,我就用數據庫的副本我的電腦上執行不同的SQL查詢,這就是我的本錢:

SELECT col1, col2, col3 FROM SomeTables WHERE (id = '42') 

這一個不工作(這顯然查詢等於查詢,由第一代碼樣品產生)

SELECT col1, col2, col3 FROM SomeTables WHERE (id = 42) 

而這一工作正常(等於從第二個代碼示例查詢)。

據我所知,SQLite應該自動執行類型轉換,但出錯了,我不知道爲什麼。你有關於如何修正第一個代碼示例的任何想法嗎? (?或者,也許,數據庫)

如果它的事項,這裏的簡化CREATE表的腳本id領域:

CREATE TABLE SomeTable (ID PRIMARY KEY, col1, col2, [...]) 

UPD:而且,順便說一句,GETSID(DB)返回字符串目的。

+0

在第一個查詢中,您傳遞'42'。 SQL執行程序將始終將其作爲字符串獲取,因此您不需要使用「'」(單引號)。你可以直接給予價值。如果您當時使用「like」,則需要單引號,否則就OK。 –

回答

2

根據SQLite的documentation

在SQLite版本3數據庫的任何列,除了一個INTEGER PRIMARY KEY列,可用於存儲任何存儲類的值。

在我的情況下,這意味着我們不能確定哪些數據類型將存儲在列中。如果您可以在將數據類型放入數據庫時​​控制和轉換數據類型,那麼在將數據添加到數據庫時可以將id值轉換爲TEXT,並且可以輕鬆使用selectionArgs。但這不是我的問題的答案,因爲我必須按原樣處理數據庫內容。

所以,可能的解決方案:

一)selection串嵌入整數值而不用包裹它們變成'

cursor = builder.query(db, 
        new String[]{"col1", "col2", "col3"}, 
        "id = " + getSID(db), null, null, null, null); 

從selectionArgs兩個B)鑄造值:CAST(? as INTEGER)CAST(id AS TEXT)。我認爲,將列轉換爲TEXT是更好的解決方案,因爲右操作數總是TEXT,但左列可以是任何東西。所以:

cursor = builder.query(db, 
        new String[]{"col1", "col2", "col3"}, 
        "CAST(id AS TEXT) = ?", 
        new String[]{getSID(db)}, null, null, null); 
1

您需要將INTid轉換成string傳遞到您的查詢,因爲參數數組爲字符串類型之前。例如:

cursor = builder.query(db, new String[]{"col1", "col2", "col3"}, 
    "id = ?", new String[]{String.valueOf(getSID(db))}, null, null, null); 

爲什麼它在第二類型的查詢的原因是因爲你追加用繩子整數值int自動轉換爲字符串。例如:

int i = 10; 
String s = i + ""; //now 10 is in string 
+0

對不起,我忘了說getSID(db)返回String對象。如果它會返回int,我只是'不兼容類型'編譯錯誤。 –

+0

我更喜歡'String.valueOf(i)'的方式,我認爲它更乾淨,更易讀。 – Sajmon

+0

'String.valueOf(String)'?這是無稽之談。我也嘗試讓'getSID'返回'int'並使用'String.valueOf',但它也沒有幫助。 –

8

查詢參數只能是字符串是Android數據庫API中的一個可怕的設計錯誤。

儘管文檔中提到了什麼,您應該只對實際的字符串值使用參數;整數值可以安全地直接嵌入到SQL字符串中。 (對於斑點,你必須使用接受ContentValues的功能。)

請注意,雖然SQLite的使用dynamic typing,不同類型的值做比較在大多數情況下(SELECT 42='42';回報0)相等。 有些情況下SQLite 確實自動轉換由於type affinity(在你的情況,這將發生如果你宣佈idINTEGER)值,但這是相當違反直覺,所以不應該依靠。

+0

我試圖將'ID'字段聲明爲'ID INTEGER PRIMARY KEY'和'ID TEXT PRIMARY KEY',但它沒有幫助。有沒有辦法使用selectionArgs而不將值嵌入到選擇字符串中? –

+1

找到它了:'CAST(?as INTEGER)'很好。它看起來更骯髒的黑客,但它的作品。 –

+0

但是,我猜,'CAST(column AS TEXT)'應該是更好的解決方案。 –