Mục tiêu
Sử dụng toán tử GLOB trong SQLite để so khớp mẫu (pattern matching) theo chuẩn Unix wildcard (globbing), phân biệt chữ hoa/thường.
GLOB vs LIKE
| Đặc điểm | LIKE | GLOB |
| Wildcard nhiều ký tự | % | * |
| Wildcard 1 ký tự | _ | ? |
| Tập ký tự | Không hỗ trợ | [abc], [a-z], [^0-9] |
| Case-sensitive | Mặc định KHÔNG (ASCII) | Mặc định CÓ |
| Escape | ESCAPE '\' | Không có escape, dùng [] |
Các bước thực hiện
Bước 1: Tạo dự án mới
Android Studio → File → New Project → Empty Activity.
Bước 2: Layout (activity_main.xml) - Giống các bài trước
Bước 3: DatabaseHelper.java - Truy vấn GLOB
package com.example.sqliteglob;
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 DB_NAME = "salaryDatabase3";
private static final String TABLE_NAME = "SalaryDetails";
private static final int VERSION = 1;
DatabaseHelper(Context context) {
super(context, DB_NAME, null, VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + TABLE_NAME + " (id INTEGER PRIMARY KEY, name TEXT, salary TEXT)");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldV, int newV) {
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);
return db.insert(TABLE_NAME, null, cv) != -1;
}
// TRUY VẤN CHÍNH: WHERE name GLOB 'Sa*'
ArrayList<String> getAllContacts() {
SQLiteDatabase db = getReadableDatabase();
ArrayList<String> list = new ArrayList<>();
Cursor cursor = db.rawQuery(
"SELECT * FROM " + TABLE_NAME + " WHERE name GLOB 'Sa*'",
null
);
if (cursor.moveToFirst()) {
do {
list.add(cursor.getString(cursor.getColumnIndexOrThrow("name")));
} while (cursor.moveToNext());
}
cursor.close();
return list;
}
}
Giải thích GLOB Patterns
| Pattern | Ý nghĩa | Ví dụ khớp | Không khớp |
Sa* | Bắt đầu bằng "Sa" (case-sensitive) | Sam, Sarah, Samsung | sam, sara, SA |
*son | Kết thúc bằng "son" | Jason, Jackson | SON, Son |
[Ss]am | S hoặc s, tiếp theo "am" | Sam, sam | SAM, sAm |
[A-M]* | Bắt đầu bằng chữ A-M | Alice, Bob, John | Nancy, Zoe |
[^0-9]* | KHÔNG bắt đầu bằng số | abc, hello | 123, 9lives |
??? | Đúng 3 ký tự | Tom, Ann | Tommy, Al |
Case Sensitivity - Quan trọng!
GLOB luôn phân biệt chữ hoa/thường (case-sensitive).
'Sam' GLOB 'Sa*' → TRUE
'sam' GLOB 'Sa*' → FALSE (vì 's' ≠ 'S')
- Để case-insensitive:
WHERE lower(name) GLOB 'sa*' hoặc dùng LIKE
Kết quả
Nhập: "Sam", "sam", "Sarah", "sarah", "John"
Kết quả GLOB 'Sa*': Sam, Sarah (chỉ những cái viết hoa S, a thường)

Khi nào dùng GLOB thay vì LIKE?
- Cần case-sensitive matching (mã code, username, serial number)
- Cần character class
[abc], [a-z], [^0-9]
- Hiệu năng tốt hơn LIKE cho pattern phức tạp
- Quen thuộc với Unix shell globbing (*, ?, [...])
Tối ưu hóa
- Index hỗ trợ GLOB pattern prefix (ví dụ:
'Sa*')
CREATE INDEX idx_name ON SalaryDetails(name)
- Pattern bắt đầu bằng wildcard (
'*suffix', '?char') không dùng được index
Tóm tắt các bài SQLite (1003060913, 925, 933, 934, 935, 936)
| Toán tử | Cú pháp | Case-sensitive | Wildcard | Dùng cho |
| AND | cond1 AND cond2 | Tuỳ column | - | Kết hợp điều kiện |
| BETWEEN | col BETWEEN a AND b | Tuỳ column | - | Khoảng liên tục |
| IN | col IN (v1,v2...) | Tuỳ column | - | Danh sách rời rạc |
| NOT IN | col NOT IN (v1,v2...) | Tuỳ column | - | Loại trừ danh sách |
| LIKE | col LIKE 'pattern' | Mặc định KHÔNG | %, _ | Tìm kiếm mờ, prefix |
| GLOB | col GLOB 'pattern' | Luôn CÓ | *, ?, [...] | Exact match, char class |