2010-06-17 163 views
73

我有一個android應用程序,需要檢查數據庫中是否有記錄,如果沒有,處理一些事情並最終插入它,並且只要數據存在就從數據庫中讀取數據。我使用SQLiteOpenHelper的子類來創建並獲取SQLiteDatabase的可重寫實例,如果它不存在,我認爲它會自動處理創建表(因爲執行該操作的代碼位於onCreate(...)中。 ) 方法)。但是,當表尚不存在,並且第一個方法運行在SQLiteDatabase對象上時,我有一個查詢調用(...),我的logcat顯示「I/Database(26434)」的錯誤: sqlite返回:錯誤代碼= 1,msg =沒有這樣的表:appdata「,果然,appdata表沒有被創建。如何檢查Android SQLite數據庫中是否存在表?

任何想法爲什麼?

我正在尋找一種方法來測試表是否存在(因爲如果沒有,數據當然不在其中,並且我不需要直到我寫入它才能讀取它,這看起來似乎創建正確的表),或一種方法來確保它被創建,並且僅僅是空的,在時間上爲第一次調用查詢(...)

編輯
這是後貼下面的兩個答案:
我想我可能已經發現了這個問題。出於某種原因,我決定爲每個表創建不同的SQLiteOpenHelper,即使它們都訪問同一個數據庫文件。我認爲重構該代碼只使用一個OpenHelper,並在其onCreate內創建兩個表可能會更好...

回答

7

是的,原來在我編輯中的理論是正確的:導致onCreate方法不運行的問題是事實SQLiteOpenHelper對象應該引用數據庫,並沒有爲每個表單獨一個。將兩個表格打包成一個SQLiteOpenHelper解決了這個問題。

+0

不錯!謝謝你的工作 – Mayank 2015-01-08 05:22:14

44

我對Android SQLite API一無所知,但如果您能夠直接在SQL中與它交談,你可以這樣做:

create table if not exists mytable (col1 type, col2 type); 

這將確保表總是被創建的,如果它已經存在,不會拋出任何錯誤。

+0

這就是我如何在SQLiteOpenHelper類中的onCreate方法創建表。在android中,建議讓該類創建表,因爲它允許應用程序自動更新其數據庫,並且通常顯然更高效。 不幸的是,執行代碼非常類似於你所寫的代碼的代碼塊沒有得到及時運行:( – camperdave 2010-06-17 05:18:16

+0

這很好,也適用於索引,即:「創建索引,如果不存在[...]」。 – 2013-07-22 18:43:43

+4

這實際上是問題的最佳答案 – 2016-04-05 03:00:28

2

您提到您已創建了一個擴展SQLiteOpenHelper並實施onCreate方法的類。你是否確定你正在執行與該類的所有數據庫獲取調用?您只能通過SQLiteOpenHelper#getWritableDatabasegetReadableDatabase獲取SQLiteDatabase對象,否則在必要時將不會調用onCreate方法。如果您正在執行此操作,請檢查是否正在調用SQLiteOpenHelper#onUpgrade方法。如果是這樣,那麼數據庫版本號在某個時間點發生了變化,但是在發生這種情況時從未正確創建表。另外,您可以通過確保與數據庫的所有連接都已關閉並調用Context#deleteDatabase,然後使用SQLiteOpenHelper爲您提供新的數據庫對象來強制重新創建數據庫。

+0

嗯,我通過getWritableDatabase()調用獲取數據庫對象,對不起,我忘了指定它 另外, m確保onUpgrade()沒有被調用,因爲該方法有一個Log.d(...)調用作爲我在數據庫中沒有看到的第一行,我會嘗試刪除整個數據庫文件,並且我們會看看是否以某種方式修復它... – camperdave 2010-06-17 14:50:51

+0

不幸的是,刪除整個數據庫(我用root explorer來清除文件)沒有 不行。我在我的應用程序中使用了兩個表格 - 其中一個完美初始化,但另一個一直給我帶來麻煩的卻沒有。 – camperdave 2010-06-17 14:54:51

0

no such table exists: error即將到來,因爲一旦您創建數據庫與一個表之後,每當你在同一個數據庫中創建表,它會給出此錯誤。

要解決此錯誤,您必須創建新數據庫並在onCreate()方法內部可以在同一數據庫中創建多個表。

9

這是我做過什麼:

/* open database, if doesn't exist, create it */ 
SQLiteDatabase mDatabase = openOrCreateDatabase("exampleDb.db", SQLiteDatabase.CREATE_IF_NECESSARY,null); 

Cursor c = null; 
boolean tableExists = false; 
/* get cursor on it */ 
try 
{ 
    c = mDatabase.query("tbl_example", null, 
     null, null, null, null, null); 
     tableExists = true; 
} 
catch (Exception e) { 
    /* fail */ 
    Log.d(TAG, tblNameIn+" doesn't exist :((("); 
} 

return tableExists; 
109

試試這個:

public boolean isTableExists(String tableName, boolean openDb) { 
    if(openDb) { 
     if(mDatabase == null || !mDatabase.isOpen()) { 
      mDatabase = getReadableDatabase(); 
     } 

     if(!mDatabase.isReadOnly()) { 
      mDatabase.close(); 
      mDatabase = getReadableDatabase(); 
     } 
    } 

    Cursor cursor = mDatabase.rawQuery("select DISTINCT tbl_name from sqlite_master where tbl_name = '"+tableName+"'", null); 
    if(cursor!=null) { 
     if(cursor.getCount()>0) { 
          cursor.close(); 
      return true; 
     } 
        cursor.close(); 
    } 
    return false; 
} 
+0

非常感謝。很棒。 +1 – Gray 2012-01-18 03:44:47

+1

大幫忙!謝謝。 – 2012-01-18 18:43:13

+9

不要忘記'cursor.close();' – styler1972 2012-05-07 21:31:28

10

儘管目前已經有很多很好的回答這個問題,我想出了另一種解決方案,我認爲更簡單。圍繞您的查詢嘗試塊和以下catch:

catch (SQLiteException e){ 
    if (e.getMessage().contains("no such table")){ 
      Log.e(TAG, "Creating table " + TABLE_NAME + "because it doesn't exist!"); 
      // create table 
      // re-run query, etc. 
    } 
} 

它爲我工作!

+1

將if語句放在if()塊中不是更好嗎?它看起來像SQLiteException由於另一個原因而不是「沒有這樣的表」引發,日誌將表明你正在創建表,而實際上不是。 – 2012-08-23 08:37:38

+0

你是對的......很好! – robguinness 2012-08-23 09:45:27

-1

..... Toast t = Toast.makeText(context,「try ...」,Toast.LENGTH_SHORT); t.show();

Cursor callInitCheck = db.rawQuery("select count(*) from call", null); 

    Toast t2a = Toast.makeText(context, "count rows " + callInitCheck.getCount() , Toast.LENGTH_SHORT); 
    t2a.show(); 

    callInitCheck.moveToNext(); 
    if(Integer.parseInt(callInitCheck.getString(0)) == 0) // if no rows then do 
    { 
     // if empty then insert into call 

.....

0
// @param db, readable database from SQLiteOpenHelper 

public boolean doesTableExist(SQLiteDatabase db, String tableName) { 
     Cursor cursor = db.rawQuery("select DISTINCT tbl_name from sqlite_master where tbl_name = '" + tableName + "'", null); 

    if (cursor != null) { 
     if (cursor.getCount() > 0) { 
      cursor.close(); 
      return true; 
     } 
     cursor.close(); 
    } 
    return false; 
} 
  • 源碼維護包含在數據庫中的所有表和索引的信息SQLITE_MASTER表。
  • 所以在這裏我們只是簡單地在它上面運行SELECT命令,如果表存在的話,我們會得到遊標數爲1。
+1

考慮提供對您的代碼的解釋 – arghtype 2015-07-11 14:31:14

0
public boolean isTableExists(String tableName) { 
    boolean isExist = false; 
    Cursor cursor = db.rawQuery("select DISTINCT tbl_name from sqlite_master where tbl_name = '" + tableName + "'", null); 
    if (cursor != null) { 
     if (cursor.getCount() > 0) { 
      isExist = true; 
     } 
     cursor.close(); 
    } 
    return isExist; 
} 
相關問題