一、移植前准备工作
1、下载源码、解压:
https://sqlite.org/download.html 中的 Source Code 下的sqlite-autoconf-3350400.tar.gz;
tar –zxvf sqlite-autoconf-3210000.tar.gz 解压成 sqlite-autoconf-3350400。
2、开发环境搭建
(1)在sqlite-autoconf-3350400平级处创建文件夹build,再进入sqlite-autoconf-3350400中
./configure --host=(如果SQLite移植到pc直接删除该项,会默认为gcc,移植到开发板的话填写使用的交叉编译工具,如下:./configure --host=arm-linux-gnueabihf --prefix=/home/linbo/linux/nfs/sqlite3_Arm/build)--prefix=/home/linbo/linux/nfs/sqlite3/build(存放最后配置文件的位置)
linbo@linbo:~/linux/nfs/sqlite3$ ls
sqlite-autoconf-3350400
linbo@linbo:~/linux/nfs/sqlite3$ mkdir build
linbo@linbo:~/linux/nfs/sqlite3$ ls
build sqlite-autoconf-3350400
linbo@linbo:~/linux/nfs/sqlite3$ cd build
linbo@linbo:~/linux/nfs/sqlite3/build$ pwd
/home/linbo/linux/nfs/sqlite3/build
linbo@linbo:~/linux/nfs/sqlite3/build$
注意:上述步骤如果出现错误,按以下步骤解决:
sudo apt-get install libtool
sudo apt-get install libtool-ltdl
sudo apt-get install libtool-ltdl-devel
然后将/usr/share/libtool/build-aux/config.guess 拷贝到sqlite-autoconf-3350400中;
/usr/share/libtool/build-aux/config.sub也拷贝到sqlite-autoconf-3350400中。
路径有可能随系统改变,可以使用以下命令查找出路径拷贝:
sudo find / -name config.guess
sudo find / -name config.sub
(2)执行sudo make编译并使用make install 安装,成功之后在build下面,生成以下四个文件夹
linbo@linbo:~/linux/nfs/sqlite3/sqlite-autoconf-3350400$ cd ../build/
linbo@linbo:~/linux/nfs/sqlite3/build$ ls
bin include lib share
linbo@linbo:~/linux/nfs/sqlite3/build$
bin文件夹中的文件是数据库的服务:sqlite3,拷贝至/bin中。
lib文件夹中的文件是需要用到的静态库和动态库,拷贝至/lib中。
3、验证成功
任意路径下输入sqlite3出现下图界面代表成功
linbo@linbo:~/linux/nfs/sqlite3/build/bin$ sqlite3
SQLite version 3.35.4 2021-04-02 15:20:15
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite>
二、网关表数据结构设计
sqlite3 DB_gateway.db (数据库名称:DB_gateway.db)
1、登录信息 (表名称:TABLE_login)
账号、密码
CREATE TABLE TABLE_login(ID INTEGER PRIMARY KEY,login_account TEXT, login_password TEXT);
2、云平台服务器(表名称:TABLE_cloud)
域名地址、服务器端口、用户名、密码
CREATE TABLE TABLE_cloud(ID INTEGER PRIMARY KEY,cloud_domain TEXT, cloud_port INTEGER,cloud_account TEXT,cloud_password TEXT );
3、NTP服务器配置(表名称:TABLE_NTP)
域名地址、端口
CREATE TABLE TABLE_NTP(ID INTEGER PRIMARY KEY,ntp_domain TEXT, ntp_port INTEGER);
4、串口参数:(表名称:TABLE_serial)
串口名称、开/关、波特率、有效数据位个数、停止位个数、奇偶校验方式
CREATE TABLE TABLE_serial(ID INTEGER PRIMARY KEY,serial_name TEXT,serial_switch INTEGER,serial_baudrate INTEGER,serial_date INTEGER,serial_stop INTEGER,serial_parity TEXT);
5、子设备(modbus+CAN):(表名称:TABLE_device)
在线/不在线、设备名、驱动、端口、地址码
CREATE TABLE TABLE_device(ID INTEGER PRIMARY KEY,device_line INTEGER,device_name TEXT,device_driver TEXT,device_port TEXT,device_id INTEGER);
6、CAN配置信息:(表名称:TABLE_CAN)
CAN名称、开/关、波特率、过滤使能
CREATE TABLE TABLE_CAN(ID INTEGER PRIMARY KEY,can_name TEXT,can_switch INTEGER,can_baudrate INTEGER,can_filt INTEGER);
7、CAN 子设备 (表名称:TABLE_device)
在线/不在线、设备名称、驱动、端口、地址码
同5子设备,子设备包含modbus和CAN
8、固件版本号:(表名称:TABLE_version)
版本号
CREATE TABLE TABLE_version(ID INTEGER PRIMARY KEY,version TEXT);
9、以太网:(表名称:TABLE_ETH)
dhcp开关、ip、netmask、gateway
CREATE TABLE TABLE_ETH(ID INTEGER PRIMARY KEY,dhcp INTEGER,ip TEXT,netmask TEXT,gateway TEXT);
三、SQL常用指令
注:每个命令以 ;结束,命令中type为数据类型,有如下类型:NULL、INTEGER、REAL、TEXT、BLOB,若未指定类型,默认是字符串,为TEXT类型。
- 创建新表: sqlite > create table <table_name> (f1 type1, f2type2,...);
- 删除表: sqlite > drop table <table_name>;
- 查询表中所有记录: sqlite >select * from<table_name>;
- 按指定条件查询表中记录: sqlite >select * from <table_name>where <expression>;
- 向表中添加新纪录: sqlite >insert into <table_name>values(value1,value2,...);
- 按指定的条件删除表中记录:sqlite >delete from <table_name>where <expression>;
- 更新表中记录: sqlite > updata <table_name> set<f1=value1>,<f2=value2>... where <expression>;
- 在表中添加字段: sqlite > alter table <table> addcolumn <field><type> defalut... ;
四、sqlite3编程接口
1. 函数原型:int sqlite3_open(char *path, sqlite3 **db);
功能:打开数据库
参数: char *path: 数据库的名字
sqlite3 **db: 数据库句柄
返回值:成功返回0,失败返回错误码(非零值)
2. 函数原型:int sqlite3_close(sqlite3*db);
功能: 关掉数据库
返回值:成功返回0,失败返回错误码
3. 函数原型:const char *sqlite3_errmsg(sqlite3 *db);
功能:提取错误信息
4. 函数原型:int sqlite3_exec(sqlite3 *db, const char *sql, sqlite3_callback callback,void *, char **errmsg);
功能: 执行一条sqlite3的语句
参数: sqlite3 *db
char *sql: sql命令语句
sqlite3_callbackcallback: 回调函数,如果命令带有返回信息,就会调用该函数
void * : 给回调函数传递参数
char**errmsg : 错误信息
返回值:成功返回0,失败返回错误码
5. 函数原型:typedef int (*sqlite3_callback) (void *para, int f_num, char **f_value,char **f_name);
功能:每找到一条记录自动执行一次回调函数
参数:para:传递给回调函数的参数
f_num:记录中包含的字段数目
f_value:包含每个字段值的指针数组
f_name:包含每个字段名称的指针数组
返回值:成功返回0,失败返回-1
6. 函数原型:int sqlite3_get_table(sqlite3*db, const char *sql, char ***resultp, int*nrow, int *ncolumn, char **errmsg);
功能:执行SQL操作,会把所有的结果一次性返回给我们,而sqlite3_callback函数返回多次
参数:db: 数据库句柄
*sql: sql命令语句
resultp: 用来指向sql执行结果的指针,所有结果还包括标题
nrow : 满足条件的记录的数目,比如记录12345、‘wang’、‘m’、24算一个
ncolumn:每条记录包含的字段数目,比如sno、sname等
errmsg:错误信息指针的地址
返回值:成功返回0,失败返回错误码
五、代码编写
#include <stdio.h>
#include <stdlib.h>
#include "sqlite3.h"
#include "sqlite3_api.h"
#define _DEBUG_
int main(int argc,char *argv[])
{
sqlite3 *db = NULL;
char *zErrMsg = 0;
int rc;
char *sql;
rc = sqlite3_open("DB_gateway.db", &db); //打开指定的数据库文件,如果不存在将创建一个同名的数据库文件
if(rc)
{
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return 0;
}
printf("You have opened DB_gateway.db successfully!\n");
//创建一个表,如果该表存在,则不创建,并给出提示信息,存储在 zErrMsg 中
char *sql1[MAX_TABLE_NUM] = {
"CREATE TABLE TABLE_login(\
ID INTEGER PRIMARY KEY,\
login_account TEXT, \
login_password TEXT);",
"CREATE TABLE TABLE_cloud(\
ID INTEGER PRIMARY KEY,\
cloud_domain TEXT,\
cloud_port INTEGER,\
cloud_account TEXT,\
cloud_password TEXT);",
"CREATE TABLE TABLE_NTP(\
ID INTEGER PRIMARY KEY,\
ntp_domain TEXT,\
ntp_port INTEGER);",
"CREATE TABLE TABLE_serial(\
ID INTEGER PRIMARY KEY,\
serial_name TEXT,\
serial_switch INTEGER,\
serial_baudrate INTEGER,\
serial_date INTEGER,\
serial_stop INTEGER,\
serial_parity TEXT);",
"CREATE TABLE TABLE_device(\
ID INTEGER PRIMARY KEY,\
device_line INTEGER,\
device_name TEXT,\
device_driver TEXT,\
device_port TEXT,\
device_id INTEGER);",
"CREATE TABLE TABLE_CAN(\
ID INTEGER PRIMARY KEY,\
can_name TEXT,\
can_switch INTEGER,\
can_baudrate INTEGER,\
can_filt INTEGER);",
"CREATE TABLE TABLE_version(\
ID INTEGER PRIMARY KEY,\
version TEXT);",
"CREATE TABLE TABLE_ETH(\
ID INTEGER PRIMARY KEY,\
dhcp INTEGER,\
ip TEXT,\
netmask TEXT,\
gateway TEXT);"
};
for(int i=0;i<MAX_TABLE_NUM;i++){
sqlite3_exec(db,sql1[i],0,0,&zErrMsg);
#ifdef _DEBUG_
printf("zErrMsg = %s \n", zErrMsg);
#endif
}
if(NULL == zErrMsg){
//插入默认数据
sql = "INSERT INTO \"TABLE_login\" VALUES(NULL ,'admin', 'admin');" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
sql = "INSERT INTO \"TABLE_cloud\" VALUES(NULL ,'www.baidu.com', 8000 , 'admin', 'admin');" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
sql = "INSERT INTO \"TABLE_NTP\" VALUES(NULL , 'www.baidu.com', 9000);" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
sql = "INSERT INTO \"TABLE_serial\" VALUES(NULL , 'RS485_1' , 1 , 9600, 8,1,'N');" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
sql = "INSERT INTO \"TABLE_serial\" VALUES(NULL , 'RS485_2' , 1 , 9600, 8,1,'N');" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
sql = "INSERT INTO \"TABLE_serial\" VALUES(NULL , 'RS485_3' , 1 , 9600, 8,1,'N');" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
sql = "INSERT INTO \"TABLE_serial\" VALUES(NULL , 'RS485_4' , 1 , 9600, 8,1,'N');" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
// sql = "INSERT INTO \"TABLE_device\" VALUES(NULL , 34 , 45 , '200605011306', 15.4 );" ;
// sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
sql = "INSERT INTO \"TABLE_CAN\" VALUES(NULL , 'CAN_1', 1 , 10000, 1 );" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
sql = "INSERT INTO \"TABLE_version\" VALUES(NULL , 'VERSION_1.1' );" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
sql = "INSERT INTO \"TABLE_ETH\" VALUES(NULL , 1 , '192.168.1.100' , '255.255.255.0', '192.168.1.1');" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
printf("zErrMsg is NULL!! \n");
}else{
printf("zErrMsg is had!! \n");
}
int nrow = 0, ncolumn = 0;
char **azResult; //二维数组存放结果
//查询数据
sql = "SELECT * FROM TABLE_ETH ";
sqlite3_get_table( db , sql , &azResult , &nrow , &ncolumn , &zErrMsg );
int i = 0 ;
printf( "row:%d column=%d \n" , nrow , ncolumn);
printf( "\nThe result of querying is : \n" );
for( i=0 ; i<( nrow + 1 ) * ncolumn ; i++ )
printf( "azResult[%d] = %s\n", i , azResult[i] );
//删除数据
sql = "DELETE FROM TABLE_ETH WHERE ID = 1 ;" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
#ifdef _DEBUG_
printf("zErrMsg = %s \n", zErrMsg);
#endif
sql = "SELECT * FROM TABLE_ETH ";
sqlite3_get_table( db , sql , &azResult , &nrow , &ncolumn , &zErrMsg );
printf( "\n\n\n\nrow:%d column=%d " , nrow , ncolumn );
printf( "\nAfter deleting , the result of querying is : \n" );
for( i=0 ; i<( nrow + 1 ) * ncolumn ; i++ )
printf( "azResult[%d] = %s\n", i , azResult[i] );
//释放掉 azResult 的内存空间
sqlite3_free_table( azResult);
#ifdef _DEBUG_
printf("zErrMsg = %s \n", zErrMsg);
#endif
sqlite3_close(db); //关闭数据库
return 0;
}