Hàm CHANGES()
Trả về số dòng bị ảnh hưởng (INSERT/UPDATE/DELETE) bởi câu lệnh SQL gần nhất trong cùng kết nối. Khác với last_insert_rowid() (trả về ID), CHANGES() trả về số lượng.
Ví dụ: Đếm số dòng thay đổi
DatabaseHelper.java
package com.example.changesdemo;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import java.util.ArrayList;
class DatabaseHelper extends SQLiteOpenHelper {
static final String DB_NAME = "salaryDatabase";
static final String TABLE = "SalaryDetails";
DatabaseHelper(Context context) {
super(context, DB_NAME, null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + TABLE +
"(id INTEGER PRIMARY KEY, name TEXT, salary REAL, datetime DEFAULT CURRENT_TIMESTAMP)");
}
@Override
public void onUpgrade(SQLiteDatabase db, int old, int n) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE);
onCreate(db);
}
boolean insert(String name, String salary) {
SQLiteDatabase db = getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put("name", name);
cv.put("salary", salary);
db.insert(TABLE, null, cv);
return true;
}
// CHANGES() trả về số dòng insert/update/delete gần nhất
ArrayList<String> getAllContacts() {
ArrayList<String> list = new ArrayList<>();
SQLiteDatabase db = getReadableDatabase();
Cursor c = db.rawQuery(
"SELECT CHANGES() AS fullname FROM " + TABLE, null);
if (c.moveToFirst()) {
do {
list.add("Changes: " + c.getInt(c.getColumnIndexOrThrow("fullname")));
} while (c.moveToNext());
}
c.close();
return list;
}
boolean update(String name, String salary) {
SQLiteDatabase db = getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put("name", name);
cv.put("salary", salary);
int rows = db.update(TABLE, cv, "name=?", new String[]{name});
return rows > 0;
}
boolean delete() {
SQLiteDatabase db = getWritableDatabase();
int rows = db.delete(TABLE, null, null);
return rows > 0;
}
}
Kết quả
Insert 1 bản ghi → ListView hiển thị: Changes: 1 (mỗi dòng đều là 1 vì SELECT chạy sau INSERT).
Update 3 bản ghi → Changes: 3.
Delete all 5 bản ghi → Changes: 5.
Lưu ý quan trọng
CHANGES()chỉ phản ánh câu lệnh trước đó ngay lập tức trong cùng connection.- Trong ví dụ trên, SELECT CHANGES() chạy sau INSERT/UPDATE/DELETE nên thấy kết quả.
- Nếu chạy SELECT khác giữa INSERT và CHANGES(), giá trị sẽ reset về 0.
Cách đúng trong Android: Dùng giá trị trả về API
// INSERT
long rowId = db.insert(TABLE, null, values); // rowId hoặc -1
// UPDATE
int rows = db.update(TABLE, values, whereClause, whereArgs); // số dòng ảnh hưởng
// DELETE
int rows = db.delete(TABLE, whereClause, whereArgs); // số dòng ảnh hưởng
// execSQL (không trả về count) - dùng CHANGES()
db.execSQL("DELETE FROM " + TABLE);
Cursor c = db.rawQuery("SELECT CHANGES()", null);
c.moveToFirst();
int affected = c.getInt(0);
TOTAL_CHANGES()
TOTAL_CHANGES() trả về tổng số dòng thay đổi kể từ khi mở connection. Hữu ích cho batch operations.
Kết luận
- Ưu tiên dùng giá trị trả về của
insert(),update(),delete()của SQLiteDatabase. - Chỉ dùng
CHANGES()khi buộc phải dùngexecSQL()cho DML. - Hiểu rõ scope: per-connection, per-statement.