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

news2024/11/30 15:39:39

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

sqlite3 交叉编译-CSDN博客

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

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

一、新建文件夹

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

sqliteDemo文件夹下文件如下

二、创建测试文件

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

在C文件中写入如下内容

#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为数据库句柄,后续对数据库的所有操作都通过此句柄进行传值。

使用举例:

​
sqlite3 *ppDb;

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

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

​
sqlite3_close() 

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

使用举例
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命令

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

第五个保存错误消息

使用举例一

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

使用举例二

#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_get_table

此函数为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;
}

实际执行效果如图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1555749.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQl on和where条件的区别?

MySQ L on和where条件的区别&#xff1f; on会生成临时表&#xff0c;不满足条件会置空 where 过滤数据&#xff0c;不满足的数据不会显示

推荐算法策略需求-rank model优化

1.pred_oobe (base) [rusxx]$ pwd /home/disk2/data/xx/icode/baidu/oxygen/rus-pipeline/pipeline-migrate/UserBaseActiveStatPipeline/his_session (base) [rusxx]$ sh test.sh 2. user_skill_history_dict_expt2包含userid [workxx]$ vim /home/work/xx/du-rus/du_rus_o…

在Windows上交叉编译STM32(环境搭建)

在Windows上交叉编译STM32 Keil 虽然好用&#xff0c;但是是收费的&#xff0c;不想破解怎么办~ 使用交叉编译工具&#xff01; 交叉编译工具下载 官方交叉编译工具下载连接 下载解压好后将 bin 目录写入 PATH&#xff0c; 使用命令行检测是否安装成功。 Windows 安装 make …

Docker搭建LNMP环境实战(08):安装php-fpm

1、编写php测试文件 在文件夹&#xff1a;/mnt/hgfs/dockers/test_site/www目录下创建文件&#xff1a;test.php&#xff0c;内容为&#xff1a; <?phpecho "hello world!!!!!! From test.php"; ?>2、编写php-fpm部署配置文件 在文件夹&#xff1a;/mnt/h…

鸿蒙 UIAbility和Compent 生命周期

一、UIAbility的生命周期 在UIAbility的使用过程中&#xff0c;会有多种生命周期状态&#xff0c;掌握UIAbility的生命周期&#xff0c;对于应用的开发非常重要。 1、UIAbility的生命周期 UIAbility的生命周期主要分为以下4个&#xff1a; Create---Foreground---Background---…

linux提权笔记

1 linux提权简介 Linux提权&#xff0c;简单来说&#xff0c;就是用户尝试获取高于其当前权限级别的系统访问权限的过程。在Linux系统中&#xff0c;root用户拥有最高的权限&#xff0c;能够执行任何操作&#xff0c;包括修改系统文件、安装软件、管理用户账户等。而普通用户通…

用html写一个贪吃蛇游戏

<!DOCTYPE html> <html> <head><title>贪吃蛇</title><meta charset"UTF-8"><meta name"keywords" content"贪吃蛇"><meta name"Description" content"这是一个初学者用来学习的小…

智慧公厕厂家如何选择?光明源智能科技打造一流智慧公厕项目

在当今城市化进程中&#xff0c;智慧公厕已经成为提升城市品质、改善市民生活的重要一环。然而&#xff0c;要打造一流的智慧公厕项目&#xff0c;选择合适的厂家显得尤为重要。作为行业领军者&#xff0c;光明源智能科技在智慧公厕领域具有丰富的经验和卓越的技术实力。今天&a…

使用倒模耳机壳UV树脂胶液制作HIFI耳机隔音降噪耳机壳推荐的材料和工艺流程?

对于使用倒模耳机壳UV树脂胶液制作HIFI耳机隔音降噪耳机壳&#xff0c;以下是一些推荐的材料和工艺流程&#xff1a; 材料&#xff1a; UV树脂胶液&#xff1a;选择适合倒模工艺的UV树脂胶液&#xff0c;要求具有高透明度、良好的流动性和固化性能。模具材料&#xff1a;根据…

SpringCloudAlibaba服务消费者调用nacos服务报错:java.net.UnknownHostException: xxx

确保服务情况正常 通过服务名字调用(注意不需要添加端口号) RequestMapping("/add") public String add() {String url "http://stock-nacos/stock/reduce";String result restTemplate.getForObject(url, String.class);System.out.println("下单…

【电子取证篇】哈希校验值的变与不变

【电子取证篇】哈希校验值的变与不变 哈希值&#xff08;散列值&#xff09;是针对电子数据内容来计算的&#xff0c;内容变则哈希变&#xff1b;但计算对象的文件名、文件时间等属性改变不会影响散列值&#xff01;&#xff01;&#xff01;—【蘇小沐】 &#xff08;一&…

软件设计不是CRUD(16):低耦合模块设计理论——行为抽象与设计模式(下)

(接上文《软件设计不是CRUD(15):低耦合模块设计理论——行为抽象与设计模式(中)》) 3.2.4、之前的业务逻辑需要关注后续逻辑的执行成败,并调整自身执行的情况 这个场景在之前场景的基础上增加了新的控制要求,具体来说就是之前已经完成的控制逻辑执行,需要在后续控制…

【讲解下go和java的区别】

&#x1f525;博主&#xff1a;程序员不想YY啊&#x1f525; &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家&#x1f4ab; &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 &#x1f308;希望本文对您有所裨益&#xff0c;如有…

基于java+springboot+vue实现的电商个性化推荐系统(文末源码+Lw+ppt)23-389

摘 要 伴随着我国社会的发展&#xff0c;人民生活质量日益提高。于是对电商个性化推荐进行规范而严格是十分有必要的&#xff0c;所以许许多多的信息管理系统应运而生。此时单靠人力应对这些事务就显得有些力不从心了。所以本论文将设计一套电商个性化推荐系统&#xff0c;帮…

uniapp-打包IOS的APP流程

打包前所需配置 在manifest文件内配置 1. APP图标 2. 启动界面 有三种启动界面配置 第一种是 HBuilderX 官方给的通用启动界面&#xff0c;页面单一&#xff0c;屏幕中间就一个圆框图标 第二种是自定义的启动图&#xff0c;无法通过AppStore的审核 第三种是自定义storyboard启动…

数据结构:单调栈和单调队列

文章目录 一、单调栈1.1、栈的思想1.2、单调栈1.2.1、单调栈的基本应用&#xff1a;找出数组中每个元素右侧第一个更大的元素1.2.2、单调栈的基本应用&#xff1a;找出数组中每个元素左侧第一个更大的元素1.2.3、单调栈拓展1.2.4、单调栈LeetCode题单 二、单调队列2.1、队列的思…

C++项目——集群聊天服务器项目(八)用户登录业务

在第&#xff08;7&#xff09;节中&#xff0c;已经实现用户注册模块&#xff0c;本节来实现用户登录模块 项目流程 1、项目环境搭建 C项目——集群聊天服务器项目(一)项目介绍、环境搭建、Boost库安装、Muduo库安装、Linux与vscode配置_c集群聊天服务器-CSDN博客 2、Jso…

Linux(5)底层分析-常见问题-经典笔试面试题整理

六、底层分析 1、linux 目录 Linux各路径的解释&#xff1a; /bin存放二进制可执行文件(ls,cat,mkdir等)&#xff0c;常用命令一般都在这里/home存放所有用户文件的根目录&#xff0c;是用户主目录的基点&#xff0c;比如用户user的主目录是/home/user&#xff0c;可以用~us…

iOS - Runtime - Class-方法缓存(cache_t)

文章目录 iOS - Runtime - Class-方法缓存(cache_t)1. 散列表的存取值 iOS - Runtime - Class-方法缓存(cache_t) Class内部结构中有个方法缓存&#xff08;cache_t&#xff09;&#xff0c;用散列表&#xff08;哈希表&#xff09;来缓存曾经调用过的方法&#xff0c;可以提高…

A fatal error occurred: MD5 of file does not match data in flash!问题解决

采用的芯片是ESP32-S3-WROOM&#xff0c;16MB FLASH 开发环境是Arduino&#xff0c;烧录到100%后直接报错。 以为是Arduino的问题&#xff0c;用esp-idf开发的程序&#xff0c; 烧录的过程中&#xff0c;也是直接报错如下&#xff1a; esptool.py v4.7.0 Serial port /dev/…