sqlite3

简介

SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中

本文章介绍在Linux环境下使用SQLite3,对于SQLite 命令的学习可以参考文章sqlite教程

安装 SQLite3 开发库

通过包管理器进行安装

bash 复制代码
sudo apt-get install libsqlite3-dev

API接口

sqlite3_open

打开数据库

c 复制代码
int sqlite3_open(
  const char *filename,  /* 数据库文件名 */
  sqlite3 **ppDb         /* 数据库连接对象的指针 */
);

参数说明

  1. *const char filename:
    • 类型: const char *
    • 描述: 数据库文件的路径。如果文件不存在,SQLite 会尝试创建一个新的数据库文件。
    • 特殊值:
      • ":memory:": 打开一个内存数据库,数据不会持久化到磁盘。
      • "" (空字符串): 打开一个临时数据库文件,该文件会在关闭数据库连接时自动删除。
  2. **sqlite3 ppDb:
    • 类型: sqlite3 **
    • 描述: 指向 sqlite3* 类型的指针,用于存储数据库连接对象。如果成功打开数据库,*ppDb 将指向一个新的数据库连接对象。

返回值

  • int: 返回值表示执行结果的状态码。
    • SQLITE_OK: 数据库成功打开。
    • SQLITE_ERROR: 通用错误。
    • SQLITE_BUSY: 数据库文件被其他进程锁定。
    • SQLITE_CANTOPEN: 无法打开数据库文件。
    • 其他状态码: 表示其他类型的错误。

sqlite3_exec

执行 SQL 命令

c 复制代码
int sqlite3_exec(
  sqlite3*,                /* 数据库连接 */
  const char *sql,         /* 要执行的 SQL 语句 */
  sqlite_callback,         /* 回调函数 */
  void *data,              /* 传递给回调函数的数据 */
  char **errmsg            /* 错误消息 */
);

参数说明

  1. sqlite3*:
    • 类型: sqlite3*
    • 描述: 数据库连接对象的指针。这个对象是由 sqlite3_open 或 sqlite3_open_v2 函数打开数据库时返回的。
  2. *const char sql:
    • 类型: const char *
    • 描述: 要执行的 SQL 语句字符串。这个字符串可以包含一个或多个 SQL 语句,用分号分隔。
  3. sqlite_callback:
    • 类型: sqlite_callback

    • 描述: 回调函数指针。当 SQL 语句返回结果集时,这个回调函数会被调用。回调函数的原型如下:

      int callback(void *data, int argc, char **argv, char **azColName);
      
      • void *data: 传递给回调函数的用户数据指针。
      • int argc: 结果集中列的数量。
      • char **argv: 结果集中每一列的值。argv[0] 是第一列的值,argv[1] 是第二列的值,依此类推。
      • char **azColName: 结果集中每一列的名称。azColName[0] 是第一列的名称,azColName[1] 是第二列的名称,依此类推。
    • 注意: 如果 SQL 语句不返回结果集(例如 INSERT, UPDATE, DELETE 等),回调函数不会被调用。

  4. *void data:
    • 类型: void *
    • 描述: 传递给回调函数的用户数据指针。这个指针可以在回调函数中使用,以便在回调函数中访问外部数据。
  5. **char errmsg:
    • 类型: char **
    • 描述: 如果 SQL 语句执行失败,错误消息将存储在这个指针指向的字符串中。调用者需要负责释放这个字符串的内存,使用 sqlite3_free 函数。
    • 注意: 如果 SQL 语句执行成功,*errmsg 将被设置为 NULL

返回值

  • int: 返回值表示执行结果的状态码。
    • SQLITE_OK: SQL 语句成功执行。
    • SQLITE_ERROR: SQL 语句执行失败。
    • 其他状态码: 表示其他类型的错误(例如 SQLITE_BUSY, SQLITE_MISUSE 等)。

sqlite3_close

关闭数据库

c 复制代码
int sqlite3_close(
  sqlite3 *db            /* 数据库连接对象 */
);

参数说明

  1. *sqlite3 db:
    • 类型: sqlite3 *
    • 描述: 要关闭的数据库连接对象的指针。这个对象是由 sqlite3_open 或 sqlite3_open_v2 函数打开数据库时返回的。

返回值

  • int: 返回值表示执行结果的状态码。
    • SQLITE_OK: 数据库成功关闭。
    • SQLITE_BUSY: 有未完成的事务或语句正在使用数据库连接。
    • 其他状态码: 表示其他类型的错误。

举例说明

创建表

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h> 

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

int main(int argc, char* argv[])
{
   sqlite3 *db;
   char *zErrMsg = 0;
   int  rc;
   char *sql;

   /* Open database */
   rc = sqlite3_open("test.db", &db);
   if( rc ){
      fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
      exit(0);
   }else{
      fprintf(stdout, "Opened database successfully\n");
   }

   /* Create SQL statement */
   sql = "CREATE TABLE COMPANY("  \
         "ID INT PRIMARY KEY     NOT NULL," \
         "NAME           TEXT    NOT NULL," \
         "AGE            INT     NOT NULL," \
         "ADDRESS        CHAR(50)," \
         "SALARY         REAL );";

   /* Execute SQL statement */
   rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
   if( rc != SQLITE_OK ){
   fprintf(stderr, "SQL error: %s\n", zErrMsg);
      sqlite3_free(zErrMsg);
   }else{
      fprintf(stdout, "Table created successfully\n");
   }
   sqlite3_close(db);
   return 0;
}

插入表

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h>

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

int main(int argc, char* argv[])
{
   sqlite3 *db;
   char *zErrMsg = 0;
   int rc;
   char *sql;

   /* Open database */
   rc = sqlite3_open("test.db", &db);
   if( rc ){
      fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
      exit(0);
   }else{
      fprintf(stderr, "Opened database successfully\n");
   }

   /* Create SQL statement */
   sql = "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) "  \
         "VALUES (1, 'Paul', 32, 'California', 20000.00 ); " \
         "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) "  \
         "VALUES (2, 'Allen', 25, 'Texas', 15000.00 ); "     \
         "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)" \
         "VALUES (3, 'Teddy', 23, 'Norway', 20000.00 );" \
         "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)" \
         "VALUES (4, 'Mark', 25, 'Rich-Mond ', 65000.00 );";

   /* Execute SQL statement */
   rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
   if( rc != SQLITE_OK ){
      fprintf(stderr, "SQL error: %s\n", zErrMsg);
      sqlite3_free(zErrMsg);
   }else{
      fprintf(stdout, "Records created successfully\n");
   }
   sqlite3_close(db);
   return 0;
}

显示

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h>

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

int main(int argc, char* argv[])
{
   sqlite3 *db;
   char *zErrMsg = 0;
   int rc;
   char *sql;
   const char* data = "Callback function called";

   /* Open database */
   rc = sqlite3_open("test.db", &db);
   if( rc ){
      fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
      exit(0);
   }else{
      fprintf(stderr, "Opened database successfully\n");
   }

   /* Create SQL statement */
   sql = "SELECT * from COMPANY";

   /* Execute SQL statement */
   rc = sqlite3_exec(db, sql, callback, (void*)data, &zErrMsg);
   if( rc != SQLITE_OK ){
      fprintf(stderr, "SQL error: %s\n", zErrMsg);
      sqlite3_free(zErrMsg);
   }else{
      fprintf(stdout, "Operation done successfully\n");
   }
   sqlite3_close(db);
   return 0;
}

限制显示表数据并且使用cJson打印数据

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h>
#include <cjson/cJSON.h>
#include <string.h>

static int callback(void *data, int argc, char **argv, char **azColName) {
    cJSON *root = (cJSON *)data;
    cJSON *item = cJSON_CreateObject();

    for (int i = 0; i < argc; i++) {
        if (strcmp(azColName[i], "ID") == 0) {
            cJSON_AddNumberToObject(item, "id", atoi(argv[i]));
        } else if (strcmp(azColName[i], "NAME") == 0) {
            cJSON_AddStringToObject(item, "name", argv[i]);
        } else if (strcmp(azColName[i], "AGE") == 0) {
            cJSON_AddNumberToObject(item, "age", atoi(argv[i]));
        } else if (strcmp(azColName[i], "ADDRESS") == 0) {
            cJSON_AddStringToObject(item, "address", argv[i]);
        } else if (strcmp(azColName[i], "SALARY") == 0) {
            cJSON_AddNumberToObject(item, "salary", atof(argv[i]));
        }
    }

    cJSON_AddItemToArray(root, item);
    return 0;
}

// 回调函数来获取总条数
static int count_callback(void *data, int argc, char **argv, char **azColName) {
    int *count = (int *)data;
    *count = atoi(argv[0]);
    return 0;
}

int main(int argc, char* argv[]) {
    sqlite3 *db;
    char *zErrMsg = 0;
    int rc;
    char *sql;
    cJSON *root = cJSON_CreateObject();
    cJSON *data_array = cJSON_CreateArray();

    // 默认值
    int limit = 10; // 每页显示的条数
    int offset = 0; // 偏移量

    // 从命令行参数中读取 limit 和 offset
    if (argc > 1) {
        limit = atoi(argv[1]);
    }
    if (argc > 2) {
        offset = atoi(argv[2]);
    }

    /* Open database */
    rc = sqlite3_open("test.db", &db);
    if (rc) {
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        exit(0);
    } else {
        fprintf(stderr, "Opened database successfully\n");
    }

    /* 获取总条数 */
    sql = "SELECT COUNT(*) FROM COMPANY";
    int total_count = 0;
    rc = sqlite3_exec(db, sql, count_callback, &total_count, &zErrMsg);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
        sqlite3_close(db);
        cJSON_Delete(root);
        return 1;
    }

    /* Create SQL statement with pagination */
    char sql_buffer[256];
    snprintf(sql_buffer, sizeof(sql_buffer), "SELECT * FROM COMPANY LIMIT %d OFFSET %d", limit, offset);
    sql = sql_buffer;

    /* Execute SQL statement */
    cJSON_AddItemToObject(root, "data", data_array);
    rc = sqlite3_exec(db, sql, callback, data_array, &zErrMsg);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    } else {
        // 添加总条数到 JSON 输出
        cJSON_AddNumberToObject(root, "total", total_count);
        cJSON_AddNumberToObject(root, "limit", limit);
        cJSON_AddNumberToObject(root, "offset", offset);
        char *json_string = cJSON_Print(root);
        fprintf(stdout, "JSON data: %s\n", json_string);
        cJSON_free(json_string);
    }
    sqlite3_close(db);
    cJSON_Delete(root);
    return 0;
}

编译和执行

  1. 编译

    bash 复制代码
    gcc -o view view.c -lcjson -lsqlite3
  2. 执行

    c 复制代码
    ./view 10 0

打印结果

bash 复制代码
{
  "data": [
    {
      "id": 1,
      "name": "张三",
      "age": 32,
      "address": "北京市",
      "salary": 5000.0
    },
    {
      "id": 2,
      "name": "李四",
      "age": 28,
      "address": "上海市",
      "salary": 6000.0
    }
    // ... 其他查询结果
  ],
  "total": 100,  // 总记录数
  "limit": 10,   // 每页显示条数
  "offset": 0    // 偏移量
}
相关推荐
AAA.建材批发刘哥1 小时前
Linux快速入门-Linux文件系统管理
linux·运维·服务器·c语言·学习方法
Kisorge2 小时前
【C语言】指针数组、数组指针、函数指针、指针函数、函数指针数组、回调函数
c语言·开发语言
爱吃西瓜的小菜鸡6 小时前
【C语言】判断回文
c语言·学习·算法
FeboReigns8 小时前
C++简明教程(文章要求学过一点C语言)(1)
c语言·开发语言·c++
FeboReigns9 小时前
C++简明教程(文章要求学过一点C语言)(2)
c语言·开发语言·c++
_小柏_9 小时前
C/C++基础知识复习(43)
c语言·开发语言·c++
yoyobravery9 小时前
c语言大一期末复习
c语言·开发语言·算法
落羽的落羽13 小时前
【落羽的落羽 C语言篇】自定义类型——结构体
c语言
一行玩python14 小时前
sqlite3,一个轻量级的 C++ 数据库库!
开发语言·数据库·c++·oracle·sqlite
Kisorge14 小时前
【C语言】代码BUG排查方式
c语言·开发语言·bug