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

Android SQLite 插入資料失敗:getReadableDatabase vs getWritableDatabase

     編輯:程式設計綜合問答

錯誤現象

新手開發 Android App 時,資料庫插入操作報錯,程式碼邏輯看似正確:

// 錯誤寫法
SQLiteDatabase db = dbHelper.getReadableDatabase();
db.execSQL("INSERT INTO dict VALUES (null, ?, ?)", new String[]{word, detail});

Logcat 顯示類似 attempt to write a readonly database 或無明顯錯誤但資料未寫入。

根本原因

SQLiteOpenHelper 提供兩個方法取得 SQLiteDatabase 實例:

方法回傳資料庫狀態適用場景
getReadableDatabase() 唯讀 (若磁碟空間不足或資料庫損壞,可能回傳唯讀) 純查詢操作 (SELECT)
getWritableDatabase() 讀寫 (若無法取得寫入權限會拋出異常) 增、刪、改操作 (INSERT, UPDATE, DELETE)

插入資料屬於寫入操作,**必須使用 getWritableDatabase()**。

修正程式碼

public class DictActivity extends Activity {
    private MyDatabaseHelper dbHelper;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dict); // 別忘了 setContentView!
        
        dbHelper = new MyDatabaseHelper(this, "myDict.db3", null, 1);
        Button btnInsert = findViewById(R.id.insert);
        
        btnInsert.setOnClickListener(v -> {
            String word = ((EditText)findViewById(R.id.word)).getText().toString();
            String detail = ((EditText)findViewById(R.id.detail)).getText().toString();
            
            // 正確:取得可寫入資料庫
            SQLiteDatabase db = dbHelper.getWritableDatabase();
            db.execSQL("INSERT INTO dict (word, detail) VALUES (?, ?)", 
                       new Object[]{word, detail}); // 建議用 Object[] 避免型別問題
            db.close(); // 良好習慣:用完關閉
            
            Toast.makeText(this, "插入成功", Toast.LENGTH_SHORT).show();
        });
    }
}

補充最佳實踐

  1. 使用 ContentValues 替代原始 SQL:防止 SQL 注入、自動處理特殊字元、可讀性更高。
    ContentValues values = new ContentValues();
    values.put("word", word);
    values.put("detail", detail);
    long newRowId = db.insert("dict", null, values);
    
  2. 在背景執行緒操作資料庫:避免 ANR,使用 AsyncTask、RxJava、Coroutines 或 Room (官方推薦 ORM)。
  3. 關閉資源:Cursor、SQLiteDatabase 用完即關,防洩漏。
  4. 升級資料庫:正確實作 onUpgrade() 處理結構變更。

結論

Android SQLite 寫入操作**務必呼叫 getWritableDatabase()**。這是新手最常犯的低級錯誤,改對方法、加上 ContentValues 與背景執行緒,資料庫操作即穩定可靠。

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