主页 > 电脑硬件  > 

数据库-SQLite

数据库-SQLite

目录

1.SQLite介绍

2.SQLite特性

3.SQLite使用

3.1.环境准备

3.2.创建数据库文件

3.3.操作数据库

4.API接口

4.1.封装数据库句柄结构体

4.2.数据库句柄初始化

4.3.连接数据库

4.4.创建表 插入数据 修改数据 删除数据

4.5.执行查询语句

4.6.初始化存储查询结果句柄

4.7.获取每一行查询结果

4.8.释放查询结果集

5.完整代码

6.总结


1.SQLite介绍

        SQLite 是一个轻量级的关系型数据库管理系统(RDBMS),广泛应用于桌面应用程序、移动设备和小型服务端应用中。它的主要特点是不需要一个独立的数据库服务器,而是通过嵌入到应用程序中运行。SQLite 使用一个简单的数据库文件存储所有数据,因此可以方便地进行数据的传输和备份。它支持 ACID(原子性、一致性、隔离性、持久性)事务,保证数据的可靠性。

2.SQLite特性

        优点:不需要配置、数据库文件小、支持跨平台、支持标准 SQL,并且非常适合用于嵌入式系统和低并发的应用。它在移动设备和桌面应用程序中非常流行,尤其是作为本地存储的数据库解决方案。在SQLite中,一个文件可以类似的看成MySQL中的数据库,即一个文件就是一个数据库。

        缺点:不适合高并发的应用、对于大规模数据处理可能性能不如 MySQL、PostgreSQL。

3.SQLite使用 3.1.环境准备

        需要安装sqlite3相关的安装包,参考ubuntu命令:apt-get install sqlite3 libsqlite3-dev

3.2.创建数据库文件

        使用 vim 在任意目录创建一个文件,后缀名没有要求,例如:vim test.sql

3.3.操作数据库

        创建好文件之后就可以操作该数据库了,例如:sqlite3 test.sql

        之后便可以创建表,然后进行增删改查操作。

4.API接口 4.1.封装数据库句柄结构体 typedef struct _DBHandle { sqlite3 *db; sqlite3_stmt *stmt; char **res; int column_num; }DBHandle;

        db:sqlite3自带的数据库处理句柄

        stmt:sqlite3保存查询句柄

        res:用于保存查询结果的每一行

        column_num:查询结果的列数

        注:此结构体可以根据实际调整,具体为什么要这样实现可以参考MySql的机制。

4.2.数据库句柄初始化

        初始化只需要将数据库句柄赋值为0即可。

/* 数据库句柄初始化 */ void db_sqlite_init(DBHandle *db_handle) { memset(db_handle, 0, sizeof(DBHandle)); return; } 4.3.连接数据库

        连接数据库即打开sqlite3数据库文件的过程,调用sqlite3原生接口。

SQLITE_API int sqlite3_open( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb /* OUT: SQLite db handle */ ); /* 连接数据库 */ int db_sqlite_connect(DBHandle *db_handle, const char *file_name) { int result = sqlite3_open(file_name, &db_handle->db); if (result != SQLITE_OK) { printf("Can't open database: %s\n", sqlite3_errmsg(db_handle->db)); return DB_FAILED; } return DB_SUCCESS; } 4.4.创建表 插入数据 修改数据 删除数据

        创建表 插入数据 修改数据 删除数据不需要获取查询结果,调用sqlite3操作sql语句的接口即可。

SQLITE_API int sqlite3_exec( sqlite3*, /* An open database */ const char *sql, /* SQL to be evaluated */ int (*callback)(void*,int,char**,char**), /* Callback function */ void *, /* 1st argument to callback */ char **errmsg /* Error msg written here */ ); /* 创建表 插入数据 修改数据 删除数据 */ int db_sqlite_execute(DBHandle *db_handle, const char *sql) { char *err_msg = NULL; int result = sqlite3_exec(db_handle->db, sql, 0, 0, &err_msg); if (result != SQLITE_OK) { printf("Failed execute sql, errmsg: %s.", err_msg); sqlite3_free(err_msg); return DB_FAILED; } return DB_SUCCESS; } 4.5.执行查询语句

        执行查询语句需要传递 stmt 参数,同时调用sqlite3接口sqlite3_prepare_v2

SQLITE_API int sqlite3_prepare_v2( sqlite3 *db, /* Database handle */ const char *zSql, /* SQL statement, UTF-8 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); /* 执行查询语句 */ int db_sqlite_query(DBHandle *db_handle, const char *sql) { int result = sqlite3_prepare_v2(db_handle->db, sql, -1, &db_handle->stmt, 0); if (result != SQLITE_OK) { printf("Failed to prepare statement: %s\n", sqlite3_errmsg(db_handle->db)); return DB_FAILED; } return DB_SUCCESS; } 4.6.初始化存储查询结果句柄

        初始话查询结果句柄 res,其实就是给 res 分配内存空间,用于保存每一行的查询结果。

/* 初始化存储查询结果句柄 */ int db_sqlite_fetch_init(DBHandle *db_handle) { db_handle->column_num = sqlite3_column_count(db_handle->stmt); db_handle->res = (char **)malloc(sizeof(char *) * db_handle->column_num ); if (!db_handle->res) { printf("Failed to malloc memory for db_handle->res."); return DB_FAILED; } memset(db_handle->res, 0, sizeof(char *) * db_handle->column_num ); return DB_SUCCESS; } 4.7.获取每一行查询结果

        获取每一行查询结果,循环调用 sqlite3_step 函数,直到没有数据为止。

        注:此处为了方便统一接口,均返回char *(字符串类型),用户根据列属性自行转换。

SQLITE_API int sqlite3_step(sqlite3_stmt*); SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); /* 获取每一行查询结果 */ char **db_sqlite_fetch_data(DBHandle *db_handle) { if (!db_handle->stmt) { return NULL; } if ((sqlite3_step(db_handle->stmt)) == SQLITE_ROW) { for (int i = 0; i < db_handle->column_num; i++) { db_handle->res[i] = (char *)sqlite3_column_text(db_handle->stmt, i); } return db_handle->res; } return NULL; } 4.8.释放查询结果集

        释放查询结果集主要分两部分,一部分是释放申请的 res 内存,另外一部分是释放sqlite3使用的 stmt。

        注:为什么要这样设计可以参考MySql实现

SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt); /* 释放查询结果集 */ void db_sqlite_fetch_free(DBHandle *db_handle) { if (db_handle->res) { free(db_handle->res); } sqlite3_finalize(db_handle->stmt); }

5.完整代码

注:编译时需要链接sqlite3动态库

#include <stdio.h> #include <sqlite3.h> #include <stdlib.h> #include <string.h> #include <malloc.h> #define DB_FAILED -1 #define DB_SUCCESS 0 #define MAX_SQL_LEN 1024 typedef struct _DBHandle { sqlite3 *db; sqlite3_stmt *stmt; char **res; int column_num; }DBHandle; /* 数据库句柄初始化 */ void db_sqlite_init(DBHandle *db_handle) { memset(db_handle, 0, sizeof(DBHandle)); return; } /* 连接数据库 */ int db_sqlite_connect(DBHandle *db_handle, const char *file_name) { int result = sqlite3_open(file_name, &db_handle->db); if (result != SQLITE_OK) { printf("Can't open database: %s\n", sqlite3_errmsg(db_handle->db)); return DB_FAILED; } return DB_SUCCESS; } /* 创建表 插入数据 修改数据 删除数据 */ int db_sqlite_execute(DBHandle *db_handle, const char *sql) { char *err_msg = NULL; int result = sqlite3_exec(db_handle->db, sql, 0, 0, &err_msg); if (result != SQLITE_OK) { printf("Failed execute sql, errmsg: %s.", err_msg); sqlite3_free(err_msg); return DB_FAILED; } return DB_SUCCESS; } /* 插入数据 */ int insert_data(DBHandle *db_handle, const char *name, int age) { char sql[MAX_SQL_LEN] = {0}; sqlite3_stmt *stmt; snprintf(sql, (size_t)MAX_SQL_LEN, "INSERT INTO users (name, age) VALUES (\"%s\", %d);", name, age); printf("sql:%s\n", sql); return db_sqlite_execute(db_handle, sql); } /* 执行查询语句 */ int db_sqlite_query(DBHandle *db_handle, const char *sql) { int result = sqlite3_prepare_v2(db_handle->db, sql, -1, &db_handle->stmt, 0); if (result != SQLITE_OK) { printf("Failed to prepare statement: %s\n", sqlite3_errmsg(db_handle->db)); return DB_FAILED; } return DB_SUCCESS; } /* 初始化存储查询结果句柄 */ int db_sqlite_fetch_init(DBHandle *db_handle) { db_handle->column_num = sqlite3_column_count(db_handle->stmt); db_handle->res = (char **)malloc(sizeof(char *) * db_handle->column_num ); if (!db_handle->res) { printf("Failed to malloc memory for db_handle->res."); return DB_FAILED; } memset(db_handle->res, 0, sizeof(char *) * db_handle->column_num ); return DB_SUCCESS; } /* 获取每一行查询结果 */ char **db_sqlite_fetch_data(DBHandle *db_handle) { if (!db_handle->stmt) { return NULL; } if ((sqlite3_step(db_handle->stmt)) == SQLITE_ROW) { for (int i = 0; i < db_handle->column_num; i++) { db_handle->res[i] = (char *)sqlite3_column_text(db_handle->stmt, i); } return db_handle->res; } return NULL; } /* 释放查询结果集 */ void db_sqlite_fetch_free(DBHandle *db_handle) { if (db_handle->res) { free(db_handle->res); } sqlite3_finalize(db_handle->stmt); } /* 查询users表数据 */ int query_users(DBHandle *db_handle) { const char *sql = "SELECT * FROM users;"; if (db_sqlite_query(db_handle, sql) != DB_SUCCESS) { return DB_FAILED; } if (db_sqlite_fetch_init(db_handle) != DB_SUCCESS) { return DB_FAILED; } while (db_sqlite_fetch_data(db_handle)) { printf("ID: %d, Name: %s, Age: %d\n", atoi(db_handle->res[0]), db_handle->res[1], atoi(db_handle->res[2])); } db_sqlite_fetch_free(db_handle); return DB_SUCCESS; } /* 更新users表数据 */ int update_users(DBHandle *db_handle, const char *name, int age, int id) { char sql[MAX_SQL_LEN] = {0}; sqlite3_stmt *stmt; snprintf(sql, (size_t)MAX_SQL_LEN, "UPDATE users SET name = \"%s\", age = %d WHERE id = %d;", name, age, id); return db_sqlite_execute(db_handle, sql); } /* 删除users表数据 */ int delete_users(DBHandle *db_handle, const char *name) { char sql[MAX_SQL_LEN] = {0}; sqlite3_stmt *stmt; snprintf(sql, (size_t)MAX_SQL_LEN, "DELETE FROM users WHERE name = \"%s\";", name); return db_sqlite_execute(db_handle, sql); } int main() { DBHandle db_hanle; db_sqlite_init(&db_hanle); db_sqlite_connect(&db_hanle, "./test.db"); /* 建表 */ if (db_sqlite_execute(&db_hanle, "CREATE TABLE IF NOT EXISTS users (""id INTEGER PRIMARY KEY AUTOINCREMENT,""name TEXT NOT NULL,""age INTEGER NOT NULL);")) { sqlite3_close(db_hanle.db); return DB_FAILED; } /* 插入数据 */ if (insert_data(&db_hanle, "Tom", 25) != DB_SUCCESS) { sqlite3_close(db_hanle.db); return DB_FAILED; } /* 插入数据 */ if (insert_data(&db_hanle, "Jerry", 30) != DB_SUCCESS) { sqlite3_close(db_hanle.db); return DB_FAILED; } printf("Users:\n"); if (query_users(&db_hanle) != DB_SUCCESS) { sqlite3_close(db_hanle.db); return DB_FAILED; } if (update_users(&db_hanle, "Jack", 18, 1) != DB_SUCCESS) { sqlite3_close(db_hanle.db); return DB_FAILED; } printf("\nAfter Update:\n"); if (query_users(&db_hanle) != DB_SUCCESS) { sqlite3_close(db_hanle.db); return DB_FAILED; } if (delete_users(&db_hanle, "Jerry") != DB_SUCCESS) { sqlite3_close(db_hanle.db); return DB_FAILED; } printf("\nAfter Delete:\n"); if (query_users(&db_hanle) != DB_SUCCESS) { sqlite3_close(db_hanle.db); return DB_FAILED; } sqlite3_close(db_hanle.db); return 0; }

运行结果:

6.总结

         SQLite 是一个轻量级的嵌入式关系型数据库管理系统,它不依赖独立的服务器进程,而是直接嵌入到应用程序中。SQLite 通过一个文件存储整个数据库,所有的数据、表、索引和视图都保存在这个文件里。简单、易用、无需配置、占用资源少、支持跨平台。

标签:

数据库-SQLite由讯客互联电脑硬件栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“数据库-SQLite