Tình huống lỗiBạn đã viết mã, định nghĩa bảng và nhấn 'Run'—nhưng ứng dụng lại bị crash ngay lập tức. Đây là một vấn đề đau đầu kinh điển trong phát triển Android. Bạn vừa thêm một bảng mới hoặc thay đổi schema, nhưng logcat lại báo một lỗi khó chịu:
android.database.sqlite.SQLiteException: no such table: users (code 1 SQLITE_ERROR)
Hệ thống khẳng định rằng bảng không tồn tại, mặc dù bạn có thể thấy câu lệnh CREATE TABLE ngay trong tệp Java hoặc Kotlin của mình. Sự mất kết nối này xảy ra do cơ sở dữ liệu trên thiết bị không đồng bộ với mã nguồn trong IDE của bạn.
Tại sao lỗi này xảy raHệ điều hành Android hoạt động hiệu quả, nhưng đôi khi cũng khá "bướng bỉnh". Lỗi này thường xuất phát từ cách hệ thống quản lý vòng đời của cơ sở dữ liệu. Dưới đây là các nguyên nhân chính:
- Bẫy onCreate(): Phương thức
onCreate()trongSQLiteOpenHelperchỉ chạy đúng một lần: khi tệp cơ sở dữ liệu được tạo lần đầu tiên. Nếu bạn thêm bảng 'users' vào mã sau khi ứng dụng đã được cài đặt,onCreate()sẽ không chạy lại. Tệp cơ sở dữ liệu cũ vẫn tồn tại và thiếu bảng mới của bạn.- Số phiên bản cũ: Bạn đã thay đổi schema nhưng vẫn giữDATABASE_VERSION = 1. Android sẽ không kích hoạt cập nhật trừ khi số đó tăng lên.- Tính an toàn của Room Migration: Room có cơ chế bảo vệ rất nghiêm ngặt. Nếu bạn thay đổi các lớp@Entitymà không cung cấp lộ trình migration, Room thường sẽ mặc định báo lỗi thay vì mạo hiểm làm mất dữ liệu.- Phân biệt chữ hoa chữ thường và lỗi đánh máy: Mặc dù SQL thường không phân biệt chữ hoa chữ thường, nhưng SQLite có thể khắt khe với các dấu ngoặc kép và khớp chuỗi chính xác trong các truy vấn phức tạp.## Các bước khắc phục### 1. Cách tiếp cận "Xóa sạch và làm lại"Nếu bạn đang ở giai đoạn đầu phát triển và không có dữ liệu người dùng quan trọng, đừng lãng phí thời gian vào các bản migration phức tạp. Hãy xóa sạch để làm lại từ đầu. - Gỡ cài đặt ứng dụng: Nhấn giữ biểu tượng ứng dụng và chọn Gỡ cài đặt. Thao tác này sẽ xóa tệp
.dbnằm trong/data/data/your.package.name/databases/. Trong lần chạy tiếp theo,onCreate()sẽ thực thi mới hoàn toàn.- Xóa bộ nhớ lưu trữ: Mở Cài đặt > Ứng dụng > [Ứng dụng của bạn] > Lưu trữ > Xóa dữ liệu. Cách này nhanh hơn việc cài đặt lại toàn bộ và mang lại kết quả tương tự.### 2. Tăng phiên bản cơ sở dữ liệuĐối với các ứng dụng sử dụngSQLiteOpenHelpertiêu chuẩn, bạn phải báo hiệu cho hệ điều hành rằng schema đã thay đổi. Hãy chuyển phiên bản từ1lên2(hoặc số nguyên tiếp theo).
public class MyDatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "UserStore.db";
// Tăng giá trị này để kích hoạt onUpgrade()
private static final int DATABASE_VERSION = 2;
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE users (id INTEGER PRIMARY KEY, username TEXT)");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion < 2) {
db.execSQL("CREATE TABLE users (id INTEGER PRIMARY KEY, username TEXT)");
}
}
}
3. Giải quyết vấn đề Migration trong RoomRoom yêu cầu các chỉ dẫn rõ ràng khi schema thay đổi. Bạn có hai con đường chính.
Destructive Migrations (Chỉ dành cho Dev)Yêu cầu Room chỉ cần xóa cơ sở dữ liệu cũ và bắt đầu lại nếu phiên bản thay đổi. Điều này ngăn chặn lỗi crash 'no such table' nhưng sẽ xóa sạch mọi dữ liệu hiện có.
database = Room.databaseBuilder(context, MyDatabase.class, "app-db")
.fallbackToDestructiveMigration()
.build();
Manual Migrations (Dành cho Production)Nếu bạn có người dùng với dữ liệu hiện có, hãy sử dụng một đối tượng migration. Điều này đảm bảo bảng 'users' được tạo trong quá trình chuyển đổi từ phiên bản 1 sang 2.
static final Migration MIGRATION_1_2 = new Migration(1, 2) {
@Override
public void migrate(SupportSQLiteDatabase database) {
database.execSQL("CREATE TABLE IF NOT EXISTS `users` (`id` INTEGER NOT NULL, `name` TEXT, PRIMARY KEY(`id`))");
}
};
Sử dụng Database InspectorĐừng đoán mò nữa. Hãy sử dụng Database Inspector của Android Studio để xem chính xác những gì có trên bộ nhớ thiết bị.
- Triển khai ứng dụng lên trình giả lập hoặc thiết bị vật lý (API 26+).- Mở tab App Inspection ở phía dưới cùng của Android Studio.- Chọn Database Inspector.- Kiểm tra danh sách bảng. Nếu
userskhông có ở đó, logiconCreatehoặconUpgradecủa bạn đã không chạy. Bạn thậm chí có thể chạySELECT * FROM userstrực tiếp trong trình kiểm tra để kiểm tra sự tồn tại của bảng trong thời gian thực.## Tổng kếtLỗi "no such table" hầu như luôn là vấn đề về phiên bản. Android chỉ đơn giản là đang cố gắng bảo vệ tệp cơ sở dữ liệu hiện có. Bằng cách tăng số phiên bản hoặc xóa dữ liệu ứng dụng, bạn buộc hệ thống phải nhận diện schema mới và tạo các bảng còn thiếu.

