首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android SQLite 重複呼叫 CREATE TABLE 會覆蓋舊表嗎?onCreate 只在資料庫首次建立時執行

     編輯:程式設計綜合問答

核心結論

不會覆蓋。SQLiteOpenHelper.onCreate(SQLiteDatabase db) **只有在資料庫檔案不存在時** 才會被呼叫一次。同一個 DBHelper 實例或多個實例,只要資料庫檔案已存在(版號相同),onCreate 就**不會再次執行**。

機制解析

  1. getWritableDatabase() / getReadableDatabase() 內部呼叫 SQLiteDatabase.openOrCreateDatabase()。
  2. 若檔案不存在 → 建立新檔 → 呼叫 onCreate(db)。
  3. 若檔案存在 → 讀取 PRAGMA user_version 取得現有版號 → 與建構子傳入的 newVersion 比較:
    • 相同 → 直接返回資料庫連線,**不呼叫 onCreate/onUpgrade**。
    • 新版號 > 舊版號 → 呼叫 onUpgrade(db, oldVersion, newVersion)。
    • 新版號 < 舊版號 → 拋出 SQLiteException(降級不支援)。

驗證實驗

public class DBHelper extends SQLiteOpenHelper {
    private static final String DB_NAME = "test.db";
    private static final int VERSION = 1;

    public DBHelper(Context context) {
        super(context, DB_NAME, null, VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        Log.d("DB", "onCreate 執行了");
        db.execSQL("CREATE TABLE IF NOT EXISTS t (id INTEGER PRIMARY KEY)");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldV, int newV) {
        Log.d("DB", "onUpgrade 執行了");
    }
}

// Activity 中
new DBHelper(this).getWritableDatabase(); // 第 1 次:印 onCreate
new DBHelper(this).getWritableDatabase(); // 第 2 次:無日誌
new DBHelper(this).getWritableDatabase(); // 第 N 次:無日誌

為何書本常見 CREATE TABLE IF NOT EXISTS?

  • 防禦性寫法:若未來手動執行 SQL、或多線程競爭建表,IF NOT EXISTS 避免拋出「table already exists」錯誤。
  • 跨平台 SQLite 直連(非 SQLiteOpenHelper)時,需自行判斷表是否存在。

版本升級時的正確做法

// 版本從 1 升至 2
private static final int VERSION = 2;

@Override
public void onUpgrade(SQLiteDatabase db, int oldV, int newV) {
    if (oldV == 1 && newV == 2) {
        db.execSQL("ALTER TABLE t ADD COLUMN name TEXT");
        // 或建立新表、遷移資料、刪舊表、改名
    }
}

總結

onCreate 由框架保證**僅在資料庫首次建立時執行一次**,重複實例化 DBHelper 不會重複建表。專注於 onUpgrade 實作平滑遷移即可。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved