Linux下利用c/c++使用sqlite

Posted Overboom

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux下利用c/c++使用sqlite相关的知识,希望对你有一定的参考价值。

参考链接:

https://blog.csdn.net/u012351051/article/details/90382391

https://blog.csdn.net/no_sying_nothing/article/details/52518822

https://cloud.tencent.com/developer/article/1018696

 

1. 安装sqlite

下载连接:https://www.sqlite.org/snapshot/sqlite-snapshot-202105251610.tar.gz

1> 解压

2>./configure

3> make

4> make install

2. sqlite常用的三个操作API

1、sqlite3_open(const char* filename, sqlite3 **ppDb);

2、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 */
    );
 
sqlite3*            : open 打开的数据库
const char* sql,    : 执行的sql功能语句
*callback,          : sql语句对应的回调函数
void* data,         : 传递给回调函数的 指针参数
char **errmsq       : 错误信息

3、sqlite3_close(sqlite3*)

3. sqlite3_exec的回调函数 callback

typedef int(*sqlite_callback)(void* para, int columenCount, char** columnValue, char** columnName);
 
参数:
para	:	由sqlite3_exec传入的参数指针【第四个参数】,或者说是指针参数 
columnCount:	查询到的这一条记录由多少个字段(多少列)
columnValue	:	该参数是双指针,查询出来的数据都保存在这里,它是一个1维数组,每一个元素都是一
                    个char*,是一个字段内容,所以这个参数就可以不是单字节,而是可以为字符串等不定
                    长度的数值,用字符串表示,以'\\0'结尾。        
columnName	:	该参数是双指针,语columnValue是对应的,表示这个字段的字段名称,
 
返回	    :	执行成果则返回SQLITE_OK,否则返回其他值                  

   这里面有几个地方容易理解错,回调函数的参数一定是 sql功能命令执行结果的进一步处理,其中para好理解,就是sqlite3_exec传递的参数,

   columnCount:表示sql功能结果的“字段”,也就是“列”的个数,没错,就是“列”的个数。

   另外需要特别注意的是:回调函数多数时候不是执行1次,而是会循环执行n次,当我们使用select进行sql功能时,往往输出的结果会是 多行,那么 有n行,就会执行n次的 回调函数。举例如下:
 

#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;
}

这个数据库中表的内容如下(这里照搬了https://www.runoob.com/sqlite/sqlite-c-cpp.html 中的例子):

"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 );";

所以执行的结果:

Opened database successfully
Callback function called: ID = 1
NAME = Paul
AGE = 32
ADDRESS = California
SALARY = 20000.0
 
Callback function called: ID = 2
NAME = Allen
AGE = 25
ADDRESS = Texas
SALARY = 15000.0
 
Callback function called: ID = 3
NAME = Teddy
AGE = 23
ADDRESS = Norway
SALARY = 20000.0
 
Callback function called: ID = 4
NAME = Mark
AGE = 25
ADDRESS = Rich-Mond
SALARY = 65000.0
 
Operation done successfully

   可以看出来,由于sql命令行为 select* from COMPANY,该命令会将表中所有信息都输出,总共5个字段(列),包含4条信息(行),所以这个回调函数会被执行4次,理解这个逻辑,非常重要。

  而且回调函数的后两个参数是 双指针 ,也就是 指针的指针,包含了2层的指向,里层的 指向是 对应具体的数据指针,外层的指向则是  数据指针序号,也可以理解成 “列”索引。我们通过这两个指针能够进一步 编写 自定义功能代码。
 

4. 打开数据库并创建表

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

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

    printf("\\n");
    return 0;
}

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

    rc = sqlite3_open("test.db", &db);  // 打开数据库
    if(rc)
    {
        fprintf(stderr, "Can't open database:%s\\n", sqlite3_errmsg(db));
//        exit(0);
        return -1;
    }
    else
    {
        fprintf(stderr,"open database succeddfully\\n");
    }

    sql = "create table company(ID INT PRIMARY KEY NOT NULL, NAME TEXT NOT NULL, AGE TEXT NOT NULL, ADDRESS CHAR(50))";

    rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg); // 执行上面sql中的命令
    if(SQLITE_OK != rc)
    {
        fprintf(stderr, "SQL error: %s\\n", zErrMsg);
    }
    else
    {
        fprintf(stdout, "create table successfully\\n");
    }

    sqlite3_close(db);
    return 0;
}

运行:需要链接sqlite3库,下面的其他操作也是如此。

gcc sqlite3test.c -o create -l sqlite3

5. 插入数据

sql语法:

insert into + 表名 (列1, 列2, ...,列n)values(对应每列的值)

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

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

    printf("\\n");
    return 0;
}

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

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

//    sql = "create table company(ID INT PRIMARY KEY NOT NULL, NAME TEXT NOT NULL, AGE TEXT NOT NULL, ADDRESS CHAR(50))";

    sql = "insert into company(ID, NAME, AGE, ADDRESS) values(1, 'Paul', 25, 'USA');\\
        insert into company(ID, NAME, AGE, ADDRESS) values(2, 'James', 28, 'JAP');\\
        insert into company(ID, NAME, AGE, ADDRESS) values(3, 'Yao', 30, 'CHA');\\
        insert into company(ID, NAME, AGE, ADDRESS) values(4, 'kobe', 38, 'USA');";

    rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
    if(SQLITE_OK != rc)
    {
        fprintf(stderr, "SQL error: %s\\n", zErrMsg);
    }
    else
    {
        fprintf(stdout, "insert table successfully\\n");
    }

    sqlite3_close(db);
    return 0;
}

6. 查询数据:

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

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

    printf("\\n");
    return 0;
}

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

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

    sql = "select * from  company;";

    rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
    if(SQLITE_OK != rc)
    {
        fprintf(stderr, "SQL error: %s\\n", zErrMsg);
    }
    else
    {
        fprintf(stdout, "select table successfully\\n");
    }

    sqlite3_close(db);
    return 0;
}

请看输出:

7. 更新并查询

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

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

    printf("\\n");
    return 0;
}

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

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

    sql = "update  company set ADDRESS = 'RUS' where ID = 3;\\
        select * from company;";

    rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
    if(SQLITE_OK != rc)
    {
        fprintf(stderr, "SQL error: %s\\n", zErrMsg);
    }
    else
    {
        fprintf(stdout, "update table successfully\\n");
    }

    sqlite3_close(db);
    return 0;
}

8. 删除并查询

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

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

    printf("\\n");
    return 0;
}

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

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

    sql = "delete from company where ID = 2;\\
        select * from company;";

    rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
    if(SQLITE_OK != rc)
    {
        fprintf(stderr, "SQL error: %s\\n", zErrMsg);
    }
    else
    {
        fprintf(stdout, "delete table successfully\\n");
    }

    sqlite3_close(db);
    return 0;
}

 

以上是关于Linux下利用c/c++使用sqlite的主要内容,如果未能解决你的问题,请参考以下文章

[linux][c/c++]代码片段02

如何在Linux下用C/C++语言操作数据库sqlite3

SQLite 片段函数实现不会在 TextView 中将文本格式化为 HTML

在Linux下如何开发C程序?

使用片段从数据库 SQLite 获取数据时出错

十个最值得阅读学习的 C/C++ 开源项目