SQLite - C/C++ cho người mới bắt đầu

Xin chào các bạn học lập trình! Hôm nay, chúng ta sẽ bắt đầu một hành trình thú vị vào thế giới của SQLite bằng C/C++. Đừng lo lắng nếu bạn chưa từng viết một dòng mã trước đây - chúng ta sẽ bắt đầu từ những điều cơ bản và dần dần nâng cao. Cuối cùng của bài hướng dẫn này, bạn sẽ ngạc nhiên với những gì bạn có thể thực hiện!

SQLite - C/C++

SQLite là gì?

Trước khi chúng ta nhảy vào mã, hãy hiểu SQLite là gì. Hãy tưởng tượng bạn có một cuốn sổ tay kỹ thuật số nơi bạn có thể lưu trữ tất cả các loại thông tin một cách có tổ chức. Đó chính là SQLite - một cơ sở dữ liệu轻型, dựa trên tệp mà không yêu cầu một tiến trình máy chủ riêng biệt. Nó giống như có một cơ sở dữ liệu mini ngay trong túi của bạn!

Các API Giao diện C/C++

Để tương tác với SQLite bằng C/C++, chúng ta cần sử dụng thứ gọi là API (Application Programming Interfaces). Hãy tưởng tượng những công cụ đặc biệt này cho phép chương trình C/C++ của chúng ta giao tiếp với SQLite. Dưới đây là các API chính chúng ta sẽ sử dụng:

Chức năng API Mô tả
sqlite3_open() Mở kết nối đến cơ sở dữ liệu SQLite
sqlite3_exec() Thực hiện các câu lệnh SQL
sqlite3_close() Đóng kết nối cơ sở dữ liệu
sqlite3_errmsg() Trả về thông báo lỗi

Đừng lo lắng nếu những điều này có vẻ rùng rợn bây giờ. Chúng ta sẽ khám phá từng cái với nhiều ví dụ!

Kết nối đến cơ sở dữ liệu

Hãy bắt đầu bằng cách kết nối đến cơ sở dữ liệu. Điều này giống như mở cuốn sổ tay kỹ thuật số của chúng ta để bắt đầu viết.

#include <stdio.h>
#include <sqlite3.h>

int main() {
sqlite3 *db;
int rc = sqlite3_open("test.db", &db);

if (rc) {
fprintf(stderr, "Không thể mở cơ sở dữ liệu: %s\n", sqlite3_errmsg(db));
return(0);
} else {
fprintf(stderr, "Mở cơ sở dữ liệu thành công\n");
}

sqlite3_close(db);
return 0;
}

Giải thích:

  1. Chúng ta bao gồm các header cần thiết: stdio.h cho đầu vào/đầu ra và sqlite3.h cho các hàm SQLite.
  2. Trong main(), chúng ta khai báo một con trỏ đến sqlite3, đại diện cho kết nối cơ sở dữ liệu của chúng ta.
  3. Chúng ta sử dụng sqlite3_open() để mở (hoặc tạo) một cơ sở dữ liệu có tên là "test.db".
  4. Chúng ta kiểm tra xem kết nối có thành công hay không. Nếu không, chúng ta in ra một thông báo lỗi.
  5. Cuối cùng, chúng ta đóng kết nối cơ sở dữ liệu với sqlite3_close().

Tạo một bảng

Bây giờ chúng ta đã mở sổ tay, hãy tạo một trang để lưu trữ thông tin. Trong ngôn ngữ cơ sở dữ liệu, chúng ta gọi nó là bảng.

int main() {
sqlite3 *db;
char *zErrMsg = 0;
int rc;

rc = sqlite3_open("test.db", &db);

if (rc) {
fprintf(stderr, "Không thể mở cơ sở dữ liệu: %s\n", sqlite3_errmsg(db));
return(0);
}

char *sql = "CREATE TABLE STUDENTS("
"ID INT PRIMARY KEY     NOT NULL,"
"NAME           TEXT    NOT NULL,"
"AGE            INT     NOT NULL,"
"GRADE          CHAR(1));";

rc = sqlite3_exec(db, sql, 0, 0, &zErrMsg);

if (rc != SQLITE_OK) {
fprintf(stderr, "Lỗi SQL: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
} else {
fprintf(stdout, "Bảng tạo thành công\n");
}

sqlite3_close(db);
return 0;
}

Trong ví dụ này:

  1. Chúng ta mở cơ sở dữ liệu như trước.
  2. Chúng ta định nghĩa một câu lệnh SQL để tạo một bảng có tên STUDENTS với các cột ID, NAME, AGE và GRADE.
  3. Chúng ta sử dụng sqlite3_exec() để thực hiện câu lệnh SQL này.
  4. Chúng ta kiểm tra xem việc thực hiện có thành công hay không và in ra một thông báo phù hợp.

Hoạt động INSERT

Tuyệt vời! Chúng ta đã có bảng. Bây giờ hãy thêm một số dữ liệu vào đó.

char *sql = "INSERT INTO STUDENTS (ID,NAME,AGE,GRADE) "
"VALUES (1, 'Alice', 20, 'A'); "
"INSERT INTO STUDENTS (ID,NAME,AGE,GRADE) "
"VALUES (2, 'Bob', 21, 'B'); ";

rc = sqlite3_exec(db, sql, 0, 0, &zErrMsg);

if (rc != SQLITE_OK) {
fprintf(stderr, "Lỗi SQL: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
} else {
fprintf(stdout, "Dữ liệu chèn thành công\n");
}

Ở đây, chúng ta đang chèn hai bản ghi vào bảng STUDENTS. Câu lệnh SQL sử dụng cú pháp INSERT INTO để thêm mới các hàng.

Hoạt động SELECT

Bây giờ, hãy lấy lại dữ liệu chúng ta vừa chèn. Đây là nơi thực sự kỳ diệu của cơ sở dữ liệu tỏa sáng!

static int callback(void *NotUsed, int argc, char **argv, char **azColName) {
for(int i = 0; i < argc; i++) {
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
printf("\n");
return 0;
}

// Trong main()
char *sql = "SELECT * from STUDENTS";
rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);

if (rc != SQLITE_OK) {
fprintf(stderr, "Lỗi SQL: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
} else {
fprintf(stdout, "Hoạt động hoàn thành thành công\n");
}

Ví dụ này giới thiệu một hàm callback. Khi chúng ta SELECT dữ liệu, SQLite gọi hàm này cho mỗi hàng trong kết quả. Nó giống như có một người giúp việc đọc từng mục trong sổ tay của chúng ta!

Hoạt động UPDATE

Nếu chúng ta phạm lỗi và cần thay đổi một số dữ liệu, hoạt động UPDATE sẽ giúp chúng ta.

char *sql = "UPDATE STUDENTS set GRADE = 'A' where ID=2";
rc = sqlite3_exec(db, sql, 0, 0, &zErrMsg);

if (rc != SQLITE_OK) {
fprintf(stderr, "Lỗi SQL: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
} else {
fprintf(stdout, "Dữ liệu cập nhật thành công\n");
}

Câu lệnh SQL này thay đổi điểm số của Bob thành A. Chúc mừng Bob!

Hoạt động DELETE

Đôi khi, chúng ta cần xóa dữ liệu. Hãy xem cách xóa một bản ghi.

char *sql = "DELETE from STUDENTS where ID=2";
rc = sqlite3_exec(db, sql, 0, 0, &zErrMsg);

if (rc != SQLITE_OK) {
fprintf(stderr, "Lỗi SQL: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
} else {
fprintf(stdout, "Bản ghi xóa thành công\n");
}

Điều này xóa bỏ bản ghi của Bob khỏi bảng. Xấu số cho Bob!

Và thế là xong! Chúng ta đã bao gồm các khía cạnh cơ bản của việc làm việc với SQLite trong C/C++. Nhớ rằng lập trình giống như học một ngôn ngữ mới - nó đòi hỏi sự thực hành. Đừng nản lòng nếu mọi thứ không ngay lập tức hiểu được. Hãy tiếp tục thử nghiệm, và sớm bạn sẽ viết các ứng dụng cơ sở dữ liệu như một chuyên gia!

Credits: Image by storyset