2014-09-11 60 views
1

我使用simpleQueryForLong()方法以下列方式:SQLiteStatement.simpleQueryForLong()是不同的行爲相比,現在的文件說

mResuableStatment = DatabaseHandler.database.compileStatement(
     "SELECT MIN(timestamp) FROM " + TABLE_LOCAITON_LOGGING); 

long oldestTimestamp = mResuableStatment.simpleQueryForLong(); 
  • timestamp是表TABLE_LOCAITON_LOGGING中列的名稱。
  • 該數據庫在該點處是可讀寫的。

根據文件 - 如果沒有行的話,那麼這段代碼假設拋出SQLiteDoneException,但真正發生的事情是,當沒有行 - 的simpleQueryForLong()返回零(沒有出現任何錯誤時拋出)

什麼是更奇怪和意外,當我真正在包裝try/catch塊這個代碼,它將每時間扔SQLiteDoneException,即使有表中的行:

try { 
    long oldestTimestamp = mResuableStatment.simpleQueryForLong(); 
} catch (SQLiteDoneException e) { 
    e.printStackTrace() 
} 

在Nexus 5,Galaxy Nexus,LG G2,HTC One X上都可以看到此行爲,所有這些都運行Android KitKat。

我有點困惑,因爲這迫使我不要使用try/catch塊,因爲如果它被使用 - 無論有沒有行,總是拋出異常,反之亦然。

似乎在我測試的每個設備中 - 沒有try/catch塊,當沒有列時 - 它返回零。

請幫我理解什麼是正確的方式,我做錯了什麼,或者如果簡單的文檔是錯誤的。

回答

2

其實,我想你會發現你錯了。

select min(something) ... 

從未返回零行。它將返回最小值(如果表中有行)或者如果表中沒有行,則返回null。如果您的查詢僅在表格爲空時爲select something,則可能返回零行,因此可能值得測試。

我已經與SqlFiddle測試此,在進入的命令:

create table xyzzy(a int); 
select a from xyzzy; 
select min(a) from xyzzy; 

第一select返回零行,所述第二返回與(null)值一行。

所以我不相信這是導致異常的空表。它可能被企圖轉換爲(null)成長。

你如何「修復」這完全取決於你想要使用的數據。依靠一個空行被轉換爲零可能會或可能不是你想要的。例如,如果表中的零時間戳記,則無法區分該表格和空表格。

這可能是可以接受的,這取決於您的業務需求。

如果您需要區分,我會運行兩個查詢。第一個將從表中返回count(*)。這保證是包含數值值(無空)的單行。如果這是零,則表示該表是空的。

如果非零,然後min(column_name),你會得到一個單行與最小時間戳。如果你在那個時候得到零,你知道這是因爲最小時間戳爲零。除非在那裏有一個NULL時間戳,在這種情況下,你可能需要做更多的檢查。但是我認爲,如果你正確地構建了你的模式,那就不太可能。

請注意,我不會通常建議這在多用戶數據庫中,因爲它可能會導致競爭條件。但我認爲這可能是好的,因爲應該只有這個數據庫的一個「用戶」,即你的應用程序。

+0

如果是這樣,那麼爲什麼文檔中有不同的說法?以及我的代碼應該如何覆蓋這種情況? – 2014-09-11 05:08:07

+0

@Tal,它沒有。它聲明,如果查詢返回零行,它將拋出異常。我說的是'select min()'不會返回零行,它總是返回一個。 'select x'可能會返回零行,但像'select min(x)'這樣的聚合函數不會。 – paxdiablo 2014-09-11 05:11:43

+0

我不明白你的答案中的一件事:我沒有說它返回零行。我說它返回零值。正如我告訴過你的 - 當我用try/catch包裝它時 - 即使有行存在時,它總是會出現異常 – 2014-09-11 05:14:20

相關問題