Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Cách sử dụng hàm CHANGES() trong SQLite Android

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ùng execSQL() cho DML.
  • Hiểu rõ scope: per-connection, per-statement.