嵌入式下C/C++调用sqlite3简单开发

交叉编译sqlite3请关注我第一篇博文

sqlite3 交叉编译-CSDN博客

sqlite3的命令的简单使用(增删改查,创建/删除表)请关注我的上一篇博文

sqlite3嵌入式使用以及C/C++代码开发-CSDN博客

一、新建文件夹

此文件夹用于放置工程,比如我的文件夹叫sqliteDemo,将交叉编译编译好的sqlite3的lib文件夹和头文件放置在工程目录下

sqliteDemo文件夹下文件如下

二、创建测试文件

创建一个c文件,比如我的为main.c

在C文件中写入如下内容

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

int main(void)
{
    sqlite3 *ppdb;
    int ret = sqlite3_open("student.db",&ppdb);
    if(ret != SQLITE_OK)
    {
        printf("sqlite3_open Failed -- %s\n", sqlite3_errmsg(ppdb));
        exit(1);
    }
    return 0;
}

三、编译测试

执行命令 arm-linux-gnueabihf-gcc main.c -o sql -L./lib -lsqlite3

则生成一个命令 sql 的可执行文件

四、运行

将sql拷贝到开发板中的某个位置,执行 ./sql 即可运行

五、sqlite函数说明

sqlite3库函数在其官网有对应的说明,可登录其网站查阅

SQLite Home Page

其中,introduction列出了常用的几个函数,如果想看更多函数,可查看其函数列表网页List Of SQLite Functions

对于一般想小型开发,仅需掌握如下四个函数即可:

sqlite3_open()

sqlite3_close()

sqlite3_exec()

sqlite3_get_table()

下面对最常用几个函数进行介绍

sqlite3_open()

此函数功能为创建数据库,如果数据库已经创建,则打开数据库,函数原型如下Opening A New Database Connection

filename为数据库的名字,即执行 ./sqlite3 student命令时的student这个值

ppDb为数据库句柄,后续对数据库的所有操作都通过此句柄进行传值。

使用举例:

cpp 复制代码
​
sqlite3 *ppDb;

int ret = sqlite3_open("student.db", &ppDb);

if(ret != SQLITE_OK)
{ 
    printf("Open Sqlite3 Failed : %s\n",sqlite3_errmsg(ppDb));
}

​
复制代码
https://www.sqlite.org/c3ref/close.html 

此函数功能为关闭数据库,如果sqlite3对象被成功销毁并且所有相关资源都被释放,则对sqlite3_close()的调用返回SQLITE_OK。函数原型如下Closing A Database Connection

使用举例
cpp 复制代码
sqlite3 *ppDb;

int ret = sqlite3_open("student.db", &ppDb);

if(ret != SQLITE_OK)
{ 
    printf("Open Sqlite3 Failed : %s\n",sqlite3_errmsg(ppDb));
}

ret = sqlite3_close(ppDb);    //关闭数据库

if(ret != SQLITE_OK)
{ 
    printf("Release Sqlite3 Failed : %s\n",sqlite3_errmsg(ppDb));
}

sqlite3_exec()

此函数为sqlite3函数的重中之重,用它可以执行几乎所有的sqlite3命令。函数原型如下One-Step Query Execution Interface

第一个参数 sqlite3*,为一个打开的数据库的句柄,比如前面sqlite3_open函数中ppDb参数。

第二个参数为填有sql的命令行语句的字符串

第三个参数为回调函数。回调函数返回值为 int。但此参数只对有显示的命令行有效,比如:select * from student命令

第四个参数为回调函数需要传入的参数,即回调函数的第一个参数值

第五个保存错误消息

使用举例一

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

int main(void)
{
	//打开或者创建数据库文件
	sqlite3 *ppdb;
	int ret = sqlite3_open("student.db",&ppdb);
	if(ret != SQLITE_OK)
	{
		printf("Open Sqlite Failed -- %s\n",sqlite3_errmsg(ppdb));
		exit(1);
	}
	
	//创建数据表
	char *sqltCmd = "create table student (id integer, name txt, age integer);";
	ret = sqlite3_exec(ppdb, sqltCmd, NULL, NULL, NULL);
	if(ret != SQLITE_OK)
	{
		printf("sqlite3_exec1 Failed! -- %s\n", sqlite3_errmsg(ppdb));
		exit (1);
	}
	
    //再次创建数据表
	char *errmsg;
	ret = sqlite3_exec(ppdb, sqltCmd, NULL, NULL, &errmsg);	//第五个参数保存错误消息
	if(ret != SQLITE_OK)
	{
		//因为sqltCmd中的命令重复创建了数据表,所以会报错,命令行中的错误会通过errmsg指针返回
		//可以通过命令行输入两遍 sqltCmd 命令对比程序运行中的下一行打印
		printf("sqlite3_exec1 Failed! -- %s\n", sqlite3_errmsg(ppdb));
		exit (1);
	}
	
	ret = sqlite3_close(ppdb);
	if(ret != SQLITE_OK)
	{
		printf("Sqlite Release Failed -- %s\n",sqlite3_errmsg(ppdb));
		exit(1);
	}
	return 0;
}

使用举例二

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sqlite3.h"

/*
print函数每查询一行,就执行一次,故无需返回数据库的数据条数,也为行数
sql:需要传入的其它参数
colum:返回数据库的字段数,也为列数
value: 返回字段的值
name:返回字段的名称
*/
int print(void * sql, int column, char** value, char ** name)
{
	printf("第一个参数示例:%s\n",sql);
    int i;
    for(i = 0; i < column; i++)
    {
        printf("%s=%s  ", name[i], value[i]);
    }
    printf("\n");
    return 0;
}


int main(void)
{
    //创建或打开数据库
    sqlite3 *ppdb;
    int ret = sqlite3_open("student.db", &ppdb);
    if(ret != SQLITE_OK)
    {
        printf("sqlite3_open : %s\n", sqlite3_errmsg(ppdb));
        exit(1);
    }

	//创建表 student
    char* sql = "create table if not exists student (id integer, name txt, age integer);";
    ret = sqlite3_exec(ppdb, sql, NULL, NULL, NULL);
    if(ret != SQLITE_OK)
    {
        printf("sqlite3_exec1 : %s\n", sqlite3_errmsg(ppdb));
        exit(1);
    }

    char cmd[256] = {0};
    int id, age, i;
    char name[256]={0};
    for(i = 0; i < 2; i++)
    {
        printf("请输入学号、名字和年龄:\n");
        scanf("%d%s%d",&id,name,&age);
        memset(cmd, 0, sizeof(cmd));
        sprintf(cmd,"insert into student (id, name, age) values(%d, '%s', %d);",id,name,age);
        ret = sqlite3_exec(ppdb, cmd, NULL, NULL, NULL);
        if(ret != SQLITE_OK)
        {
            printf("sqlite3_exec2 : %s\n", sqlite3_errmsg(ppdb));
            exit(1);
        }
    }
	
	memset(cmd, 0, sizeof(cmd));
	sprintf(cmd,"select * from student;");
	ret = sqlite3_exec(ppdb, cmd, print, sql, NULL);//此处sql仅仅是用来说明传参问题
	if(ret != SQLITE_OK)
	{
		printf("sqlite3_exec3 : %s\n", sqlite3_errmsg(ppdb));
		exit(1);
	}
	
	ret = sqlite3_close(ppdb);
	if(ret != SQLITE_OK)
	{
		printf("sqlite3_close : %s\n", sqlite3_errmsg(ppdb));
		exit(1);
	}
    return 0;
}
    

执行效果如下

sqlite3_exec函数回调参数的再说明

以 使用举例二 为例,假如此时数据表中含有4项数据

在调用sqlite3_exec函数查询数据表时

每查询到一条数据,则调用一次 回调函数 print。

假如现在查询完第一条数据,即 1|aa|11

则返回列数为 3(形参column 为 3),数据值为 1 aa 11 的字符串(即 *value 指向{"1", "aa", "11"}的字符串首地址),字段值为 id name age 的字符串(即*name 指向{"id","name","age"}的字符串的首地址)

因此,可以通过 value[i] 和 name[i] 找到对应的字符串

此函数为sqlite3专门用于查询语句的函数,函数原型如下

Convenience Routines For Running Queries

第一个参数为数据库的句柄

第二个参数为填有sql的命令行语句的字符串

第三个参数为查询后的返回值

第四个参数为查询到数据库中数据的条数(即行数)

第五个参数为查询到数据库中数据的字段数(即列数)

第三参数pazResult为一个一维数组,存放方式为 表头,表1对应的值,表2对应的值......

仍然以前面数据库为例说明

pazResult中数据存放方式如下图所述

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

int main(void)
{
    //创建或打开数据库
    sqlite3* ppdb;
    int ret = sqlite3_open("student.db",&ppdb);
    if(ret != SQLITE_OK)
    {
        printf("sqlite3_open : %s\n", sqlite3_errmsg(ppdb));
        exit(1);
    }

    char* sql = "create table student(id integer, name text, age integer);";
    ret = sqlite3_exec(ppdb, sql, NULL, NULL, NULL);
    if(ret != SQLITE_OK)
    {
        printf("sqlite3_exec1 : %s\n", sqlite3_errmsg(ppdb));
        exit(1);
    }

    char cmd[256] = {0};
    int id, age, i, j;
    char name[128] = {0};
    for(i = 0; i < 2; i++)
    {
        printf("请输入学号、名字和年龄:\n");
        scanf("%d%s%d",&id, name, &age);
        memset(cmd, 0, sizeof(cmd));
        sprintf(cmd, "insert into student(id, name, age) values (%d, '%s', %d);",id,name,age);
        ret = sqlite3_exec(ppdb, cmd, NULL, NULL, NULL);
        if(ret != SQLITE_OK)
        {
            printf("sqlite3_exec2 : %s\n", sqlite3_errmsg(ppdb));
            exit(1);
        }
    }
    
    char **result;
    int row, column;
    memset(cmd, 0, sizeof(cmd));
    sprintf(cmd, "select * from student;");
    ret = sqlite3_get_table(ppdb, cmd, &result, &row, &column, NULL);
    if(ret != SQLITE_OK)
    {
        printf("sqlite3_get_table: %s\n", sqlite3_errmsg(ppdb));
        exit(1);
    }
	
	int Index = column;
    for(i = 0; i < row; i++)
    {
        for(j = 0; j < column; j++)
        {
            //result[j]是指的表头的三个字符串
            //result[Index]是指的实际数据,实际数据是跨过表头后从column开始的数据
            //参照上面的内存截图理解
            printf("%s=%s  ",result[j], result[Index]);
			Index++;
        }
        printf("\n");
    }

    return 0;
}

实际执行效果如图

相关推荐
wyk123_04644 分钟前
Django 连接(sqlserver)数据库方法
数据库·sqlserver·django
李长渊哦6 小时前
使用Druid连接池优化Spring Boot应用中的数据库连接
数据库·spring boot·后端
斗-匕7 小时前
Spring Boot自动装配:约定大于配置的魔法解密
数据库
铁头乔8 小时前
IoTDB 断电后无法启动 DataNode,日志提示 Meet error while starting up
数据库·开源·时序数据库·iotdb
一 乐8 小时前
高校体育场管理系统系统|体育场管理系统小程序设计与实现(源码+数据库+文档)
前端·javascript·数据库·spring boot·高校体育馆系统
来一杯龙舌兰9 小时前
【Postgresql】Windows 部署 Postgresql 数据库 (图文教程)
数据库·windows·postgresql
blog_wanghao9 小时前
C#: 创建Excel文件并在Excel中写入数据库中的数据
数据库·c#·excel
xianwu54310 小时前
反向代理模块kd
开发语言·网络·数据库·c++·mysql
vdigital10 小时前
本地主机(localhost)11434端口 HTTP 连接10061原因及解决
java·服务器·数据库
蓝牙先生10 小时前
git自动化之.netrc配置
数据库