交叉编译sqlite3请关注我第一篇博文
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库函数在其官网有对应的说明,可登录其网站查阅
其中,introduction列出了常用的几个函数,如果想看更多函数,可查看其函数列表网页List Of SQLite Functions
对于一般想小型开发,仅需掌握如下四个函数即可:
sqlite3_open()
sqlite3_close()
sqlite3_exec()
sqlite3_get_table()
下面对最常用几个函数进行介绍
此函数功能为创建数据库,如果数据库已经创建,则打开数据库,函数原型如下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函数的重中之重,用它可以执行几乎所有的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;
}
实际执行效果如图