Lưu dữ liệu bằng SQLite | Nhà phát triển Android | Android Developers
Lưu dữ liệu vào cơ sở dữ liệu là lựa chọn lý tưởng dành cho dữ liệu lặp hoặc dữ liệu có cấu trúc,
chẳng hạn như thông tin liên hệ. Trang này giả định rằng bạn đã quen dùng
cơ sở dữ liệu SQL nói chung và hướng dẫn bạn cách bắt đầu
sử dụng cơ sở dữ liệu SQLite trên Android. Những API mà bạn cần có để sử dụng cơ sở dữ liệu
trên Android được cung cấp trong gói android.database.sqlite
.
Thận trọng: Mặc dù những API này rất mạnh mẽ, nhưng lại ở cấp khá thấp
và đòi hỏi nhiều thời gian cũng như công sức khi sử dụng:
- Không có phương thức xác minh thời gian biên dịch đối với các truy vấn SQL thô. Khi biểu đồ
dữ liệu thay đổi, bạn cần phải cập nhật các truy vấn SQL bị ảnh hưởng theo cách thủ công. Quá trình
này có thể tốn nhiều thời gian và dễ xảy ra lỗi. - Bạn cần phải dùng nhiều mã nguyên mẫu để chuyển đổi giữa các đối tượng dữ liệu
và truy vấn SQL.
Vì những lý do này, bạn nên dùng
Thư viện lưu trữ Phòng
làm lớp trừu tượng để truy cập thông tin trong cơ sở dữ liệu SQLite
của ứng dụng.Mục Chính
Xác định giản đồ và hợp đồng
Một trong những nguyên tắc chính của cơ sở dữ liệu SQL là giản đồ : nội dung khai báo chính thức về cách sắp xếp cơ sở dữ liệu. Giản đồ này được phản ánh trong câu lệnh SQL mà bạn dùng để tạo cơ sở dữ liệu. Bạn nên tạo một lớp sát cánh, còn gọi là lớp hợp đồng. Lớp này chỉ định rõ bố cục tổng quan của giản đồ theo cách có mạng lưới hệ thống và tự ghi lại .
Lớp hợp đồng là một vùng chứa cho những hằng số xác lập tên của URI, bảng và cột. Lớp hợp đồng được cho phép bạn sử dụng cùng một hằng số trên toàn bộ những lớp khác trong cùng gói. Nhờ vậy, bạn hoàn toàn có thể biến hóa tên cột ở một nơi và tự động hóa vận dụng biến hóa đó trên hàng loạt mã của mình .
Một cách hiệu suất cao để sắp xếp lớp hợp đồng là đặt những định nghĩa dùng chung cho hàng loạt cơ sở dữ liệu của bạn vào Lever gốc của lớp. Sau đó, tạo một lớp bên trong cho từng bảng. Mỗi lớp bên trong sẽ liệt kê những cột của bảng tương ứng .Lưu ý: Khi triển khai giao diện
BaseColumns
, lớp bên trong của bạn có thể kế thừa trường khoá
chính có tên_ID
mà một số lớp Android nhưCursorAdapter
muốn có. Tuy không bắt buộc nhưng trường này có thể giúp cơ sở dữ liệu
hoạt động hài hoà với khung Android.Ví dụ : hợp đồng sau đây xác lập tên bảng và tên cột cho một bảng duy nhất biểu lộ nguồn cấp dữ liệu RSS :
Kotlin
object FeedReaderContract { // Table contents are grouped together in an anonymous object. object FeedEntry : BaseColumns { const val TABLE_NAME = "entry" const val COLUMN_NAME_TITLE = "title" const val COLUMN_NAME_SUBTITLE = "subtitle" } }Java
public final class FeedReaderContract { // To prevent someone from accidentally instantiating the contract class, // make the constructor private. private FeedReaderContract() {} /* Inner class that defines the table contents */ public static class FeedEntry implements BaseColumns { public static final String TABLE_NAME = "entry"; public static final String COLUMN_NAME_TITLE = "title"; public static final String COLUMN_NAME_SUBTITLE = "subtitle"; } }Tạo cơ sở dữ liệu bằng trình trợ giúp SQL
Sau khi xác lập giao diện của cơ sở dữ liệu, bạn nên tiến hành những phương pháp giúp tạo cũng như duy trì cơ sở dữ liệu và bảng. Dưới đây là 1 số ít câu lệnh thường dùng để tạo và xóa bảng :
Kotlin
private const val SQL_CREATE_ENTRIES = "CREATE TABLE ${FeedEntry.TABLE_NAME} (" + "${BaseColumns._ID} INTEGER PRIMARY KEY," + "${FeedEntry.COLUMN_NAME_TITLE} TEXT," + "${FeedEntry.COLUMN_NAME_SUBTITLE} TEXT)" private const val SQL_DELETE_ENTRIES = "DROP TABLE IF EXISTS ${FeedEntry.TABLE_NAME}"Java
private static final String SQL_CREATE_ENTRIES = "CREATE TABLE " + FeedEntry.TABLE_NAME + " (" + FeedEntry._ID + " INTEGER PRIMARY KEY," + FeedEntry.COLUMN_NAME_TITLE + " TEXT," + FeedEntry.COLUMN_NAME_SUBTITLE + " TEXT)"; private static final String SQL_DELETE_ENTRIES = "DROP TABLE IF EXISTS " + FeedEntry.TABLE_NAME;Cũng giống như những tệp bạn lưu vào bộ nhớ trong của thiết bị, Android tàng trữ cơ sở dữ liệu của bạn trong thư mục riêng tư của ứng dụng. Dữ liệu của bạn được bảo mật thông tin vì theo mặc định, những ứng dụng khác hoặc người dùng không hề truy cập vào khu vực này .
Lớp
SQLiteOpenHelper
chứa tập hợp API
hữu ích để quản lý cơ sở dữ liệu.
Khi bạn dùng lớp này để lấy thông tin tham chiếu đến cơ sở dữ liệu của mình, hệ thống
sẽ thực hiện các thao tác tạo và cập nhật cơ sở dữ liệu có khả năng kéo dài chỉ khi
cần thiết, chứ không phải lúc khởi động ứng dụng. Tất cả những gì bạn cần làm là gọi
getWritableDatabase()
hoặc
getReadableDatabase()
.Lưu ý: Vì các thao tác này có thể kéo dài,
hãy nhớ gọigetWritableDatabase()
hoặcgetReadableDatabase()
trên luồng trong nền.
Bạn có thể xem phần Tạo luồng trên Android để biết thêm thông tin.Để sử dụng
SQLiteOpenHelper
, hãy tạo một lớp con
ghi đè phương thức gọi lạionCreate()
và
onUpgrade()
. Ngoài ra, bạn cũng
nên triển khai các phương thức
onDowngrade()
hoặc
onOpen()
, nhưng
không bắt buộc.Ví dụ: dưới đây là cách triển khai
SQLiteOpenHelper
sử dụng một số lệnh nêu trên:Kotlin
class FeedReaderDbHelper(context: Context) : SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) { override fun onCreate(db: SQLiteDatabase) { db.execSQL(SQL_CREATE_ENTRIES) } override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { // This database is only a cache for online data, so its upgrade policy is // to simply to discard the data and start over db.execSQL(SQL_DELETE_ENTRIES) onCreate(db) } override fun onDowngrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { onUpgrade(db, oldVersion, newVersion) } companion object { // If you change the database schema, you must increment the database version. const val DATABASE_VERSION = 1 const val DATABASE_NAME = "FeedReader.db" } }Java
public class FeedReaderDbHelper extends SQLiteOpenHelper { // If you change the database schema, you must increment the database version. public static final int DATABASE_VERSION = 1; public static final String DATABASE_NAME = "FeedReader.db"; public FeedReaderDbHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } public void onCreate(SQLiteDatabase db) { db.execSQL(SQL_CREATE_ENTRIES); } public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // This database is only a cache for online data, so its upgrade policy is // to simply to discard the data and start over db.execSQL(SQL_DELETE_ENTRIES); onCreate(db); } public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { onUpgrade(db, oldVersion, newVersion); } }Để truy cập vào cơ sở dữ liệu của bạn, hãy tạo bản sao lớp con của
SQLiteOpenHelper
:Kotlin
val dbHelper = FeedReaderDbHelper(context)Java
FeedReaderDbHelper dbHelper = new FeedReaderDbHelper(getContext());Đưa thông tin vào cơ sở dữ liệu
Chèn dữ liệu vào cơ sở dữ liệu bằng cách chuyển đối tượng
ContentValues
vào phương thứcinsert()
:Kotlin
// Gets the data repository in write mode val db = dbHelper.writableDatabase // Create a new map of values, where column names are the keys val values = ContentValues().apply { put(FeedEntry.COLUMN_NAME_TITLE, title) put(FeedEntry.COLUMN_NAME_SUBTITLE, subtitle) } // Insert the new row, returning the primary key value of the new row val newRowId = db?.insert(FeedEntry.TABLE_NAME, null, values)Java
// Gets the data repository in write mode SQLiteDatabase db = dbHelper.getWritableDatabase(); // Create a new map of values, where column names are the keys ContentValues values = new ContentValues(); values.put(FeedEntry.COLUMN_NAME_TITLE, title); values.put(FeedEntry.COLUMN_NAME_SUBTITLE, subtitle); // Insert the new row, returning the primary key value of the new row long newRowId = db.insert(FeedEntry.TABLE_NAME, null, values);Đối số đầu tiên của
insert()
chỉ đơn thuần là tên bảng.Đối số thứ hai sẽ cho khung biết việc nên làm trong trường hợp
ContentValues
bị trống (tức là bạn không
put
giá trị nào).
Nếu bạn chỉ định tên của một cột, khung sẽ chèn một hàng và đặt
giá trị của cột đó thành rỗng. Nếu bạn chỉ địnhnull
, như trong
mã mẫu này, khung sẽ không chèn hàng khi không có giá trị.Phương thức
insert()
sẽ trả về mã nhận dạng cho
hàng mới tạo hoặc sẽ trả về -1 nếu xảy ra lỗi khi chèn dữ liệu. Trường hợp này có thể xảy ra
nếu bạn gặp xung đột với dữ liệu có sẵn từ trước trong cơ sở dữ liệu.Đọc thông tin từ cơ sở dữ liệu
Để đọc từ một cơ sở dữ liệu, hãy dùng phương thức
query()
, chuyển phương thức đó vào tiêu chí lựa chọn và cột mong muốn.
Phương thức này kết hợp các thành phần củainsert()
vàupdate()
, ngoại trừ danh sách cột
xác định dữ liệu bạn muốn tìm nạp (“phép chiếu”), thay vì dữ liệu cần chèn. Kết quả
của truy vấn sẽ được trả về cho bạn trong đối tượngCursor
.Kotlin
val db = dbHelper.readableDatabase // Define a projection that specifies which columns from the database // you will actually use after this query. val projection = arrayOf(BaseColumns._ID, FeedEntry.COLUMN_NAME_TITLE, FeedEntry.COLUMN_NAME_SUBTITLE) // Filter results WHERE "title" = 'My Title' val selection = "${FeedEntry.COLUMN_NAME_TITLE} = ?" val selectionArgs = arrayOf("My Title") // How you want the results sorted in the resulting Cursor val sortOrder = "${FeedEntry.COLUMN_NAME_SUBTITLE} DESC" val cursor = db.query( FeedEntry.TABLE_NAME, // The table to query projection, // The array of columns to return (pass null to get all) selection, // The columns for the WHERE clause selectionArgs, // The values for the WHERE clause null, // don't group the rows null, // don't filter by row groups sortOrder // The sort order )Java
SQLiteDatabase db = dbHelper.getReadableDatabase(); // Define a projection that specifies which columns from the database // you will actually use after this query. String[] projection = { BaseColumns._ID, FeedEntry.COLUMN_NAME_TITLE, FeedEntry.COLUMN_NAME_SUBTITLE }; // Filter results WHERE "title" = 'My Title' String selection = FeedEntry.COLUMN_NAME_TITLE + " = ?"; String[] selectionArgs = { "My Title" }; // How you want the results sorted in the resulting Cursor String sortOrder = FeedEntry.COLUMN_NAME_SUBTITLE + " DESC"; Cursor cursor = db.query( FeedEntry.TABLE_NAME, // The table to query projection, // The array of columns to return (pass null to get all) selection, // The columns for the WHERE clause selectionArgs, // The values for the WHERE clause null, // don't group the rows null, // don't filter by row groups sortOrder // The sort order );Đối số thứ ba và thứ tư (
selection
vàselectionArgs
) được
kết hợp để tạo mệnh đề WHERE. Vì được cung cấp riêng biệt với truy vấn
lựa chọn nên các đối số này sẽ được thoát trước khi kết hợp. Nhờ vậy, các câu lệnh lựa chọn của bạn sẽ miễn nhiễm với lệnh chèn
SQL. Để biết thêm thông tin chi tiết về tất cả đối số, hãy xem
tài liệu tham khảo vềquery()
.Để xem xét một hàng trong con trỏ, hãy dùng một trong các phương thức
di chuyểnCursor
. Bạn phải luôn gọi phương thức này trước khi bắt đầu đọc giá trị. Vì con trỏ bắt đầu ở
vị trí -1, nên lệnh gọimoveToNext()
sẽ đặt “vị trí đọc” ở
mục đầu tiên trong kết quả và trả về thông tin cho biết liệu con trỏ đã đi qua mục cuối cùng trong
tập kết quả hay chưa. Đối với mỗi hàng, bạn có thể đọc giá trị của một cột bằng cách gọi một trong các
phương thức getCursor
, chẳng hạn nhưgetString()
hoặcgetLong()
. Đối với mỗi phương thức get, bạn phải
chuyển vị trí chỉ mục của cột mong muốn. Bạn có thể lấy vị trí này bằng cách gọi
getColumnIndex()
hoặc
getColumnIndexOrThrow()
. Khi bạn hoàn tất
quá trình lặp theo kết quả, hãy gọiclose()
trên con trỏ
để giải phóng tài nguyên.
Ví dụ: nội dung sau đây cho biết cách lấy tất cả mã mục được lưu trữ trong con trỏ
và thêm các mã đó vào danh sách:Kotlin
val itemIds = mutableListOf() with(cursor) { while (moveToNext()) { val itemId = getLong(getColumnIndexOrThrow(BaseColumns._ID)) itemIds.add(itemId) } } cursor.close() Java
List itemIds = new ArrayList<>(); while(cursor.moveToNext()) { long itemId = cursor.getLong( cursor.getColumnIndexOrThrow(FeedEntry._ID)); itemIds.add(itemId); } cursor.close();Xoá thông tin khỏi cơ sở dữ liệu
Để xoá hàng khỏi bảng, bạn cần cung cấp tiêu chí lựa chọn
(giúp xác định hàng) cho phương thứcdelete()
. Cơ chế
này hoạt động giống như các đối số lựa chọn cho phương thức
query()
. Cơ chế này chia
quy cách lựa chọn thành một mệnh đề lựa chọn và các đối số lựa chọn. Mệnh đề
này xác định cột cần xem xét, đồng thời cho phép bạn kết hợp các
quá trình kiểm thử cột. Đối số là các giá trị cần kiểm thử dựa trên đối số được đưa vào mệnh đề.
Vì được xử lý không giống như câu lệnh SQL thông thường, nên kết quả này
miễn nhiễm với lệnh chèn SQL.Kotlin
// Define 'where' part of query. val selection = "${FeedEntry.COLUMN_NAME_TITLE} LIKE ?" // Specify arguments in placeholder order. val selectionArgs = arrayOf("MyTitle") // Issue SQL statement. val deletedRows = db.delete(FeedEntry.TABLE_NAME, selection, selectionArgs)Java
// Define 'where' part of query. String selection = FeedEntry.COLUMN_NAME_TITLE + " LIKE ?"; // Specify arguments in placeholder order. String[] selectionArgs = { "MyTitle" }; // Issue SQL statement. int deletedRows = db.delete(FeedEntry.TABLE_NAME, selection, selectionArgs);Giá trị trả về của phương thức
delete()
cho biết số hàng đã bị xoá khỏi cơ sở dữ liệu.Khi bạn cần sửa đổi một nhóm nhỏ giá trị cơ sở dữ liệu, hãy dùng phương thức
update()
.Thao tác cập nhật bảng sẽ kết hợp cú pháp
ContentValues
của
insert()
với cú phápWHERE
củadelete()
.Kotlin
val db = dbHelper.writableDatabase // New value for one column val title = "MyNewTitle" val values = ContentValues().apply { put(FeedEntry.COLUMN_NAME_TITLE, title) } // Which row to update, based on the title val selection = "${FeedEntry.COLUMN_NAME_TITLE} LIKE ?" val selectionArgs = arrayOf("MyOldTitle") val count = db.update( FeedEntry.TABLE_NAME, values, selection, selectionArgs)Java
SQLiteDatabase db = dbHelper.getWritableDatabase(); // New value for one column String title = "MyNewTitle"; ContentValues values = new ContentValues(); values.put(FeedEntry.COLUMN_NAME_TITLE, title); // Which row to update, based on the title String selection = FeedEntry.COLUMN_NAME_TITLE + " LIKE ?"; String[] selectionArgs = { "MyOldTitle" }; int count = db.update( FeedReaderDbHelper.FeedEntry.TABLE_NAME, values, selection, selectionArgs);Giá trị trả về của phương thức
update()
là
số hàng bị ảnh hưởng trong cơ sở dữ liệu.Duy trì kết nối cơ sở dữ liệu
getWritableDatabase()
vàgetReadableDatabase()
khá
tốn kém nếu gọi khi cơ sở dữ liệu bị đóng. Vì thế, bạn nên duy trì kết nối cơ sở dữ liệu
trong suốt thời gian cần truy cập (nếu có thể). Thông thường, bạn nên đóng cơ sở dữ liệu
trongonDestroy()
của Hoạt động gọi.
Kotlin
override fun onDestroy() { dbHelper.close() super.onDestroy() }
Java
@Override protected void onDestroy() { dbHelper.close(); super.onDestroy(); }
Gỡ lỗi cơ sở dữ liệu
SDK Android có chứa công cụ shell sqlite3
cho phép bạn duyệt xem
nội dung trong bảng, chạy lệnh SQL và thực hiện các hàm hữu ích khác trên cơ sở dữ liệu
SQLite. Để biết thêm thông tin, hãy xem cách gửi lệnh shell.
Source: https://thomaygiat.com
Category : Kỹ Thuật Số
Chuyển vùng quốc tế MobiFone và 4 điều cần biết – MobifoneGo
Muốn chuyển vùng quốc tế đối với thuê bao MobiFone thì có những cách nào? Đừng lo lắng, bài viết này của MobiFoneGo sẽ giúp…
Cách copy dữ liệu từ ổ cứng này sang ổ cứng khác
Bạn đang vướng mắc không biết làm thế nào để hoàn toàn có thể copy dữ liệu từ ổ cứng này sang ổ cứng khác…
Hướng dẫn xử lý dữ liệu từ máy chấm công bằng Excel
Hướng dẫn xử lý dữ liệu từ máy chấm công bằng Excel Xử lý dữ liệu từ máy chấm công là việc làm vô cùng…
Cách nhanh nhất để chuyển đổi từ Android sang iPhone 11 | https://thomaygiat.com
Bạn đã mua cho mình một chiếc iPhone 11 mới lạ vừa ra mắt, hoặc có thể bạn đã vung tiền và có một chiếc…
Giải pháp bảo mật thông tin trong các hệ cơ sở dữ liệu phổ biến hiện nay
Hiện nay, với sự phát triển mạnh mẽ của công nghệ 4.0 trong đó có internet và các thiết bị công nghệ số. Với các…
4 điều bạn cần lưu ý khi sao lưu dữ liệu trên máy tính
08/10/2020những chú ý khi tiến hành sao lưu dữ liệu trên máy tính trong bài viết dưới đây của máy tính An Phát để bạn…