Giới thiệu
Ví dụ này minh họa cách truy vấn các bản ghi của một ngày cụ thể (specific date) dựa trên cột timestamp (datetime) trong SQLite Android.
Bước 1: Tạo dự án mới
Mở Android Studio, chọn File → New Project và điền đầy đủ thông tin cần thiết.
Bước 2: Thiết kế giao diện (res/layout/activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<EditText
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Nhập tên" />
<EditText
android:id="@+id/salary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Nhập lương"
android:inputType="numberDecimal" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/save"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Lưu" />
<Button
android:id="@+id/refresh"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Xem ngày 13/01/2019" />
<Button
android:id="@+id/update"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cập nhật" />
<Button
android:id="@+id/delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Xóa tất cả" />
</LinearLayout>
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
Bước 3: MainActivity.java
package com.example.andy.myapplication;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
Button save, refresh, update, delete;
EditText name, salary;
ListView listView;
DatabaseHelper helper;
ArrayAdapter arrayAdapter;
ArrayList arrayList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
helper = new DatabaseHelper(this);
arrayList = new ArrayList<>(helper.getAllContacts());
name = findViewById(R.id.name);
salary = findViewById(R.id.salary);
listView = findViewById(R.id.listView);
save = findViewById(R.id.save);
refresh = findViewById(R.id.refresh);
update = findViewById(R.id.update);
delete = findViewById(R.id.delete);
arrayAdapter = new ArrayAdapter<>(this,
android.R.layout.simple_list_item_1, arrayList);
listView.setAdapter(arrayAdapter);
delete.setOnClickListener(v -> {
if (helper.deleteAll()) {
Toast.makeText(this, "Đã xóa", Toast.LENGTH_LONG).show();
refreshList();
} else {
Toast.makeText(this, "Xóa thất bại", Toast.LENGTH_LONG).show();
}
});
update.setOnClickListener(v -> {
String n = name.getText().toString().trim();
String s = salary.getText().toString().trim();
if (!n.isEmpty() && !s.isEmpty()) {
if (helper.update(n, s)) {
Toast.makeText(this, "Đã cập nhật", Toast.LENGTH_LONG).show();
refreshList();
} else {
Toast.makeText(this, "Cập nhật thất bại", Toast.LENGTH_LONG).show();
}
} else {
name.setError("Nhập tên");
salary.setError("Nhập lương");
}
});
refresh.setOnClickListener(v -> refreshList());
save.setOnClickListener(v -> {
String n = name.getText().toString().trim();
String s = salary.getText().toString().trim();
if (!n.isEmpty() && !s.isEmpty()) {
if (helper.insert(n, s)) {
Toast.makeText(this, "Đã thêm", Toast.LENGTH_LONG).show();
refreshList();
name.setText("");
salary.setText("");
} else {
Toast.makeText(this, "Thêm thất bại", Toast.LENGTH_LONG).show();
}
} else {
name.setError("Nhập tên");
salary.setError("Nhập lương");
}
});
}
private void refreshList() {
arrayList.clear();
arrayList.addAll(helper.getAllContacts());
arrayAdapter.notifyDataSetChanged();
}
}
Bước 4: DatabaseHelper.java
package com.example.andy.myapplication;
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 {
private static final String DATABASE_NAME = "salaryDatabase5";
private static final String TABLE_NAME = "SalaryDetails";
private static final int DATABASE_VERSION = 1;
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
String sql = "CREATE TABLE " + TABLE_NAME + " (" +
"id INTEGER PRIMARY KEY AUTOINCREMENT, " +
"name TEXT, " +
"salary TEXT, " +
"datetime DEFAULT CURRENT_TIMESTAMP)";
db.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}
boolean insert(String name, String salary) {
SQLiteDatabase db = getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put("name", name);
cv.put("salary", salary);
long result = db.insert(TABLE_NAME, null, cv);
return result != -1;
}
// QUAN TRỌNG: Truy vấn bản ghi theo ngày CỤ THỂ
ArrayList getAllContacts() {
SQLiteDatabase db = getReadableDatabase();
ArrayList list = new ArrayList<>();
// DATE(datetime) = 'YYYY-MM-DD' (định dạng ISO 8601)
// Ví dụ: 13-01-2019 -> '2019-01-13'
String query = "SELECT (name || ' : ' || salary || ' : ' || datetime) AS fullname " +
"FROM " + TABLE_NAME +
" WHERE DATE(datetime) = '2019-01-13'";
Cursor res = db.rawQuery(query, null);
if (res.moveToFirst()) {
do {
list.add(res.getString(res.getColumnIndexOrThrow("fullname")));
} while (res.moveToNext());
}
res.close();
if (list.isEmpty()) {
list.add("Không có bản ghi nào cho ngày 2019-01-13");
}
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_NAME, cv, null, null); // CẢNH BÁO: không WHERE
return rows > 0;
}
boolean deleteAll() {
SQLiteDatabase db = getWritableDatabase();
int rows = db.delete(TABLE_NAME, null, null);
return rows > 0;
}
}
Chạy ứng dụng
Kết nối thiết bị, nhấn Run. Thêm bản ghi với ngày 13/01/2019 (hoặc chỉnh thời gian thiết bị), nhấn Xem ngày 13/01/2019.
Kết quả
ListView hiển thị các bản ghi có datetime rơi vào ngày 13-01-2019:
Nguyễn Văn A : 10000000 : 2019-01-13 08:30:00 Trần Thị B : 15000000 : 2019-01-13 14:22:00
Giải thích truy vấn theo ngày cụ thể
Định dạng ngày chuẩn SQLite: YYYY-MM-DD (ISO 8601)
DATE(datetime) = '2019-01-13'- So sánh phần ngày của cột datetime với chuỗi cố định- SQLite tự động parse '2019-01-13' thành date
- Khớp mọi thời gian trong ngày đó (00:00:00 đến 23:59:59)
Các cách truy vấn ngày khác nhau
| Mục đích | WHERE clause |
|---|---|
| Ngày cụ thể | DATE(datetime) = '2019-01-13' |
| Khoảng ngày | DATE(datetime) BETWEEN '2019-01-01' AND '2019-01-31' |
| Tháng cụ thể | strftime('%Y-%m', datetime) = '2019-01' |
| Năm cụ thể | strftime('%Y', datetime) = '2019' |
| Ngày trong tuần (CN=0) | strftime('%w', datetime) = '1' (Thứ 2) |
Truy vấn an toàn với tham số (Parameterized Query)
// Trong Java code - an toàn SQL Injection
String targetDate = "2019-01-13";
String query = "SELECT * FROM " + TABLE_NAME + " WHERE DATE(datetime) = ?";
Cursor res = db.rawQuery(query, new String[]{targetDate});
Lưu ý: Code gốc nhúng cứng ngày '2019-01-13' trong SQL. Đã thêm giải thích định dạng ISO 8601, các hàm strftime, và cách dùng parameterized query an toàn. Cảnh báo UPDATE không WHERE.