sqlite3数据库Linux 系统移植和使用

发布时间 2023-03-22 19:13:52作者: 大龄小凡

sqlite3数据库是一个小型的数据库,当数据量不大,要求不是特别高的时候,是个不错的选择。

在Linux上移植和使用也非常的方便。

本示例是在硬件全志r528 .linux5.4 上验证的。

移植操作:

   1、源码下载

      去官网进行下载源码SQLite Download Page,根据自己的选取选择不同的版本。我发现我系统的menuconfig 上就带sqlite3的数据库,所以没有在

官网上下载,直接勾选上。编译出来的。

     

 

 

       

    2、交叉编译

  进入sqlite-autoconf-3230100后执行以下指令生成Makefile文件:

./configure CC=arm-hisiv400-linux-gcc--host=arm-hisiv400-linux--prefix=/home/rong//share/lishuangliang/sqlite/install

其中CC指定嵌入式平台为arm-hisiv400-linux-gcc即海思的Hi3536;host项指定主机;prefix项指定安装目录;

需要注意的是每一项配置的等号两边不能有空格。接着运行make进行编译,待编译完成后运行make install进行安装,

至此源码编译安装完成。(未验证)
      编译出来有用的文件有libsqlite3.so libsqlite3.so.0动态库。sqlite3 可执行文件。

    3、配置部署编译出来的库和执行文件

    将libsqlite3.so libsqlite3.so.0动态库拷贝到Linux系统的  /usr/lib/ 目录下,

        将sqlite3 拷贝到Linux系统的  /usr/bin/ 目录下面。

应用编译

    将 libsqlite3.so libsqlite3.so.0 放在要编译的应用程序一个目录或其他目录下都可以主要是编译器要能找到。

    sqlite3.h放在放在要编译的应用程序一个目录

  配置交叉编译 必须 加上 -lsqlite3  -L加上库目录 -I 加上头文件目录

  如下是一个简单的Makefile 

# 方便起见一般都会先定义编译器链接器
CC = arm-openwrt-linux-gcc 
LD = arm-openwrt-linux-gcc
FLAGS = -lsqlite3 -L /home/kerson/app/test_app/sqlit3  -I /home/kerson/app/test_app/sqlit3

# 正则表达式表示目录下所有.c文件,相当于:SRCS = main.c a.c b.c
SRCS = $(wildcard *.c)

# OBJS表示SRCS中把列表中的.c全部替换为.o,相当于:OBJS = main.o a.o b.o
OBJS = $(patsubst %c, %o, $(SRCS))

# 可执行文件的名字
TARGET = test_sqlite

# .PHONE伪目标,具体含义百度一下一大堆介绍
.PHONY:all clean

# 要生成的目标文件
all: $(TARGET)

# 第一行依赖关系:冒号后面为依赖的文件,相当于Hello: main.o a.o b.o
# 第二行规则:$@表示目标文件,$^表示所有依赖文件,$<表示第一个依赖文件
$(TARGET): $(OBJS)
    $(LD) $(FLAGS) -o $@ $^

# 上一句目标文件依赖一大堆.o文件,这句表示所有.o都由相应名字的.c文件自动生成
%.o:%.c
    $(CC) $(FLAGS) -c $^

# make clean删除所有.o和目标文件
clean:
    rm -f $(OBJS) $(TARGET)

 以上是使用动态库编译的,也可以使用静态库进行编译并且系统中不用再增加对应的库文件。

将上面的libsqlite3.so libsqlite3.so.0 动态库更改为libsqlite3.a

Makefile 以下修改,增加-lpthread -ldl  并且将 -lsqlite3 -lpthread -ldl 

放在编译的目标文件后面,否则找不到静态库。

 

# 方便起见一般都会先定义编译器链接器
CC = arm-openwrt-linux-gcc
LD = arm-openwrt-linux-gcc
FLAGS = -L/home/kerson/app/test_app/sqlit3  -I/home/kerson/app/test_app/sqlit3
ARFLAGS = -lsqlite3 -lpthread -ldl

# 正则表达式表示目录下所有.c文件,相当于:SRCS = main.c a.c b.c
SRCS = $(wildcard *.c)

# OBJS表示SRCS中把列表中的.c全部替换为.o,相当于:OBJS = main.o a.o b.o
OBJS = $(patsubst %c, %o, $(SRCS))

# 可执行文件的名字
TARGET = test_sqlite

# .PHONE伪目标,具体含义百度一下一大堆介绍
.PHONY:all clean

# 要生成的目标文件
all: $(TARGET)

# 第一行依赖关系:冒号后面为依赖的文件,相当于Hello: main.o a.o b.o
# 第二行规则:$@表示目标文件,$^表示所有依赖文件,$<表示第一个依赖文件
$(TARGET): $(OBJS)
        $(LD) $(FLAGS) -o $@ $^ $(ARFLAGS)

# 上一句目标文件依赖一大堆.o文件,这句表示所有.o都由相应名字的.c文件自动生成
%.o:%.c
        $(CC) $(FLAGS) -c $^  $(ARFLAGS)

# make clean删除所有.o和目标文件
clean:
        rm -f $(OBJS) $(TARGET)

 

问题:

链接出现undefined reference to `dlclose' 的错误

增加 -ldl 就可以了。

 

下面分享实验代码

主要是拼接SQL语句。之后用exec函数执行SQL语句。

主要的是查询表格内容时,注意回调函数是每查找到一条记录就执行一次回调函数。

 

my_sqlite3.c


#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "sqlite3.h"
#include "my_sqlite3.h"




/*
* @brief 打开/创建数据库
* @param 无
* @return 失败返回NULL/成功返回数据库db
*/

sqlite3 * sqlite3_open_database(char * db_name)
{
    int ret = 0;
    sqlite3* db;

    if(db_name == NULL || strlen(db_name) == 0){
        return NULL;
    }
    
    ret = sqlite3_open(db_name ,&db);
    if(ret != SQLITE_OK){
        printf("Open db error =:%s",sqlite3_errmsg(db));
        return NULL;
    }
    
    return db;
}


/*
* @brief 创建一个表
* @param db,
    table_name:表名字
    data_buf:列项目
* @return 失败返回-1/成功返回0
*/

int sqlite3_create_table(sqlite3 *db, char * table_name,char *data_buf)
{
    char sql_str[128] ={0};
    char *err_msg = NULL;
    int ret =-1;
    if(table_name == NULL ||strlen(table_name) ==0){
        printf("input argc error\n");
        return -1;
    }

    sprintf(sql_str,"CREATE TABLE IF NOT EXISTS %s %s",table_name,data_buf);
    ret = sqlite3_exec(db,sql_str,0,0,&err_msg);
    if(ret != SQLITE_OK)
    {
        printf("Creat table %s error : %s", table_name,err_msg);
        sqlite3_free(err_msg);
    }else{
        ret = 0;
    }

    return ret;
}




/*
* @brief 删除一个表
* @param db,
    table_name:表名字
* @return 失败返回-1/成功返回0
*/
int sqlite3_delete_table(sqlite3 *db, char * table_name)
{
    char sql_str[128] ={0};
    char *err_msg = NULL;
    int ret =-1;
    if(table_name == NULL ||strlen(table_name) ==0){
        printf("input argc error\n");
        return -1;
    }

    sprintf(sql_str,"DROP TABLE %s",table_name);
    sqlite3_busy_timeout(db, 1000);
    ret = sqlite3_exec(db,sql_str,0,0,&err_msg);
    if(ret != SQLITE_OK)
    {
        printf("Delete table %s error : %s", table_name,err_msg);
        sqlite3_free(err_msg);
    }else{
        ret = 0;
    }
    return ret;

    
}


/*
* @brief 插入一条数据
* @param db,
    table_name:表名字
* @return 失败返回-1/成功返回0
*/
int sqlite3_insert_single(sqlite3 *db,char *table_name,  char *data_buf)
{

    char sql_str[128] ={0};
    char *err_msg = NULL;
    int ret =-1;
    if(table_name == NULL ||strlen(table_name) ==0){
        printf("input argc error\n");
        return -1;
    }

    sprintf(sql_str,"INSERT INTO %s values %s",table_name,data_buf);
    sqlite3_busy_timeout(db, 1000);
    ret = sqlite3_exec(db,sql_str,0,0,&err_msg);
    if(ret != SQLITE_OK)
    {
        printf("insert table %s error : %s", table_name,err_msg);
        sqlite3_free(err_msg);
    }else{
        ret = 0;
    }
    return ret;
}



/*
* @brief 插入多条数据(利用显示事物机制,效率高)
* @param db,
    table_name:表名字
    data_buf 多条插入的内容
* @return 失败返回-1/成功返回0
*/

int sqlite3_insert_multi(sqlite3 *db,char *table_name,  char **data_buf ,int len)
{

    char sql_str[128] ={0};
    char *err_msg = NULL;
    int ret =-1 ,i =0;
    sqlite3_stmt * stmt;
    
    if(table_name == NULL ||strlen(table_name) ==0){
        printf("input argc error\n");
        return -1;
    }
    sprintf(sql_str,"INSERT INO %s values ?");

    sqlite3_exec(db,"BEGIN",0,0,0);
    ret = sqlite3_prepare(db,sql_str,strlen(sql_str),&stmt,0);
    if(ret != SQLITE_OK)
        return -1;
    
    while(data_buf[i] !=NULL && i < len){
        sqlite3_bind_text(stmt,1,data_buf[i],strlen(data_buf[i]),NULL);
        ret = sqlite3_step(stmt);
        if((ret != SQLITE_OK) && (ret != SQLITE_DONE)){
            break;
        }
        sqlite3_reset(stmt);
        i++;
    }
    sqlite3_finalize(stmt);
    if(i < len){
        sqlite3_exec(db,"ROLLBACK",0,0,0);
        return -1;
    }
    if(i == len){
        sqlite3_exec(db,"COMMIT",0,0,0);
        ret =0;
    }    


    return ret;
}



/*
* @brief 查询回调函数
* @param 

 data:由sqlite3_exec传递的初始化参数
 argc:表头的列数
 col:表头的名字数组指针
 argv:表头的数据数组指针

* @return 失返回0
*/
int exec_handle(void *data, int argc, char **argv,char ** colname)
{
    /*查询到一条结果将data+1*/    
    int i = *(int *)(data);
    *(int *)(data) = i+1;

    /*打印*/
    for(i =0;i<argc;i++){
        printf("NUM =%d %s\t%s\n",*(int *)(data),colname[i],argv[i]);
    }

    return 0;
}




/*
* @brief 查询表格内容  sql语句:SELECT 列名称 FROM 表名称 WHERE 列 运算符 值
列名称为 * 代表所有的列
* @param db,
    table_name:表名字
* @return 失败返回-1/成功返回0 查询成功,无查询结果,返回1 查询成功,有查询结果
*/
int sqlite3_select_exec(sqlite3 *db,char *table_name, char *col_name, char *where_cond)
{
    char sql_str[128] ={0};
    char *err_msg = NULL;
    int ret =-1;
    int data =0;
    if(table_name == NULL ||strlen(table_name) ==0){
        printf("input argc error\n");
        return -1;
    }

    sprintf(sql_str,"select %s from %s ",col_name,table_name);
    
    if(where_cond != NULL){
        strcat(sql_str," where ");
        strcat(sql_str,where_cond);
    }
    sqlite3_busy_timeout(db, 1000);
    ret = sqlite3_exec(db,sql_str,exec_handle,&data,&err_msg);
    if(ret != SQLITE_OK)
    {
        printf("select table %s error : %s", table_name,err_msg);
        sqlite3_free(err_msg);
    }else{

        if(data == 0){
            return 0; /*查询成功,无查询结果*/
        }else{
            return 1; /*查询成功,有查询结果*/
        }    
        
    }

}


/*
* @brief 查询数据库中的表格  sql语句:select name from sqlite_maseter where type ='table' order by name
列名称为 * 代表所有的列
* @param db,
* @return 
*/
int sqlite3_get_tablename(sqlite3 *db)
{
    char sql_str[128] ={0};
    char *err_msg = NULL;
    int ret =-1;
    char ** dbresult;
    int i,j,nrow,ncolumn,index =0;

    sprintf(sql_str,"select name from sqlite_master where type ='table' order by name ");
    
    sqlite3_busy_timeout(db, 1000);
    ret = sqlite3_get_table(db,sql_str,&dbresult,&nrow,&ncolumn,&err_msg);
    if(ret == SQLITE_OK)
    {
        for(i=0;i <= nrow; i++)
            /*for(j=0;j< ncolumn;j++)*/
        {
            printf("%s \n",dbresult[index]);
            index++;
        }
    }
    else{

        printf(" get table error\n ");
    }

}




/*
* @brief 更新 sql语句:UPDATAE 表名 SET 新值 WHERE 列 运算符 值
* @param db,
    table_name:表名字
* @return 失败返回-1/成功返回0 查询成功,无查询结果,返回1 查询成功,有查询结果
*/
int sqlite3_update_single(sqlite3 *db,char *table_name, char *new_val, char *where_cond)
{
    char sql_str[128] ={0};
    char *err_msg = NULL;
    int ret =-1;

    if(table_name == NULL ||strlen(table_name) ==0){
        printf("input argc error\n");
        return -1;
    }

    sprintf(sql_str,"UPDATE %s SET %s",table_name,new_val);
    if(where_cond != NULL){
        strcat(sql_str," where ");
        strcat(sql_str,where_cond);
    }    
    sqlite3_busy_timeout(db, 1000);
    ret = sqlite3_exec(db,sql_str,0,0,&err_msg);
    if(ret != SQLITE_OK)
    {
        printf("UPDATE table %s error : %s", table_name,err_msg);
        sqlite3_free(err_msg);
        ret =-1;
    }else{

        ret = 0;    
    }
    return ret;

}


/*
* @brief 删除 sql语句:DELETE FROM 表名称 WHERE 列 运算符 值
没有where 为删除所有。
* @param db,
    table_name:表名字
* @return 失败返回-1/成功返回0 查询成功,无查询结果,返回1 查询成功,有查询结果
*/
int sqlite3_delete_single(sqlite3 *db,char *table_name,char *where_cond)
{
    char sql_str[128] ={0};
    char *err_msg = NULL;
    int ret =-1;
    int data =0;
    if(table_name == NULL ||strlen(table_name) ==0){
        printf("input argc error\n");
        return -1;
    }

    sprintf(sql_str,"DELETE FROM %s",table_name);
    if(where_cond != NULL){
        strcat(sql_str," where ");
        strcat(sql_str,where_cond);
    }
    sqlite3_busy_timeout(db, 1000);
    ret = sqlite3_exec(db,sql_str,exec_handle,&data,&err_msg);
    if(ret != SQLITE_OK)
    {
        printf("s table %s error : %s", table_name,err_msg);
        sqlite3_free(err_msg);
        ret =-1;
    }else{

        ret = 0;    
    }
    return ret;

}

 

头文件

my_sqlite3.h

#ifndef _MY_SQLITE3_H_
#define _MY_SQLITE3_H_ sqlite3 * sqlite3_open_database(char * db_name); int sqlite3_create_table(sqlite3 *db, char * table_name,char *data_buf); int sqlite3_delete_table(sqlite3 *db, char * table_name); int sqlite3_insert_single(sqlite3 *db,char *table_name, char *data_buf); int sqlite3_select_exec(sqlite3 *db,char *table_name, char *col_name, char *where_cond); int exec_handle(void *data, int argc, char **argv,char ** colname); int sqlite3_update_single(sqlite3 *db,char *table_name, char *new_val, char *where_cond); int sqlite3_delete_single(sqlite3 *db,char *table_name,char *where_cond); int sqlite3_get_tablename(sqlite3 *db); #endif

 

 

测试代码

 

main.c


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sqlite3.h"
#include "my_sqlite3.h"

#define DB_NAME  "./test.db" 
#define DB_NAME1  "./data.db" 

#define TABLE_NAME "stu_table"
#define TABLE_NAME1 "场景表"

#define MAX_LEN 512


int main(int argc, char **argv)
{
    sqlite3 *db = NULL;
    char buf[MAX_LEN] ={0};
    char buf1[MAX_LEN] ={0};
    char *errmsg;
    int ret;

    db = sqlite3_open_database(DB_NAME);
    if(db == NULL){
        printf("open db error\n");
        return -1;
    }

    /*创建一个表*/
#if 0
    memset(sql,0,sizeof(sql));
    strcpy(sql,"creat table if not exists %s(name text ,score int);",TABLE_NAME);
    ret = sqlite3_exec(db,sql,NULL,NULL,&errmsg);
    if(ret !=0)
    {
        printf("sqlite3_exec:%s\n",errmsg);
    }
#endif
    memset(buf,0,sizeof(buf));
    strcpy(buf,"(Name text ,Score int)");
    ret = sqlite3_create_table(db,TABLE_NAME,buf);
    if(ret !=0)
    {
        return -1;
    }
    
    sqlite3_get_tablename(db); /*获取有多少表格*/


    /*插入表中*/
    memset(buf,0,sizeof(buf));
    strcpy(buf,"('lili',86)");
    ret = sqlite3_insert_single(db,TABLE_NAME,buf);
    if(ret !=0)
    {
        return -1;
    }


    /*插入表中*/
    memset(buf,0,sizeof(buf));
    strcpy(buf,"('wangwu',99)");
    ret = sqlite3_insert_single(db,TABLE_NAME,buf);
    if(ret !=0)
    {
        return -1;
    }

    /*查找*/
    printf("select all:\n");
    sqlite3_select_exec(db,TABLE_NAME,"*",NULL);
    printf("select Score > 90:\n");
    memset(buf,0,sizeof(buf));
    strcpy(buf,"Score > 90");
    sqlite3_select_exec(db,TABLE_NAME,"*",buf);
    
    /*更改*/
    memset(buf,0,sizeof(buf));
    strcpy(buf,"Score = 91");
    memset(buf1,0,sizeof(buf1));
    strcpy(buf1,"Score < 90");
    sqlite3_update_single(db,TABLE_NAME,buf,buf1);


    /*查找*/
    printf("select all:\n");
    sqlite3_select_exec(db,TABLE_NAME,"*",NULL);
    printf("select Score > 90:\n");
    memset(buf,0,sizeof(buf));
    strcpy(buf,"Score > 90");
    sqlite3_select_exec(db,TABLE_NAME,"*",buf);

    /*删除*/
    memset(buf,0,sizeof(buf));
    strcpy(buf,"Score > 90");
    sqlite3_delete_single(db,TABLE_NAME,buf);

    printf("select all:\n");
    sqlite3_select_exec(db,TABLE_NAME,"*",NULL);



    /*关闭数据库*/
    sqlite3_close(db);


    db = sqlite3_open_database(DB_NAME1);
    if(db == NULL){
        printf("open db error\n");
        return -1;
    }

    sqlite3_get_tablename(db); /*获取有多少表格*/


    /*查找*/
    printf("select all:\n");
    sqlite3_select_exec(db,TABLE_NAME1,"*",NULL);

    /*更改*/
    memset(buf,0,sizeof(buf));
    strcpy(buf,"播放亮度 = 255");
    memset(buf1,0,sizeof(buf1));
    strcpy(buf1,"场景ID = 6");
    sqlite3_update_single(db,TABLE_NAME1,buf,buf1);


    /*查找*/
    printf("select all:\n");
    sqlite3_select_exec(db,TABLE_NAME1,"*",NULL);


    /*关闭数据库*/
    sqlite3_close(db);

 
    return 0;
}

 

具体其他更细节的SQL语句,需要什么功能就百度搜索,拼接执行。

 

参考资料:

(29条消息) sqlite3数据库移植详解_dosthing的博客-CSDN博客_移植sqlite3