Linux下使用sqlite3操作数据库的总结
SQLite是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。使用时只需要添加sqlite3.h和sqlite3.c文件,这里放在一个sqlite3目录下,为调用方便,写一个封装文件db.c。首先当然是打开数据库函数:static sqlite3 *sql_db = NULL;int open_db(){if (NULL == sql_db){...
SQLite是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。使用时只需要添加sqlite3.h和sqlite3.c文件,这里放在一个sqlite3目录下,为调用方便,写一个封装文件db.c。首先当然是打开数据库函数:
static sqlite3 *sql_db = NULL;
int open_db()
{
if (NULL == sql_db)
{
return sqlite3_open("./test.db", &sql_db);
}
return SQLITE_OK;
}
为了调用方便将sql_db设置为全局变量,为空时需要打开数据库,sqlite3_open函数负责打开test.db,如果没有这个文件就创建一个空的test.db文件。有了打开数据库,当然还得有关闭数据库:
void close_db()
{
if (NULL != sql_db)
sqlite3_close(sql_db);
}
这里创建一个TAB_CONFIG表进行测试:
int ret;
char sql[1024] = {0};
strcpy(sql, "create table TAB_CONFIG(CON_ADDR integer, CON_NO integer,CON_Info varchar(20));");
ret = sqlite3_exec(sql_db, sql, NULL,NULL,NULL);
if(ret != SQLITE_OK)
{
printf("CREATE table TAB_CONFIG error!\n");
}
执行完这个命令,test.db数据库里面已经有了张空表:
下面为这个表插入一条数据:
sprintf(sql, "insert into TAB_CONFIG(CON_ADDR,CON_NO,CON_Info) values(1, 20,'%s')", "Hello world");
ret = db_exec(sql);
if (ret != SQLITE_OK)
{
printf("Table TAB_CONFIG insert data error!\n");
}
再次打开数据库来看:
表里面已经有数据了,但是我们的程序不能每次执行都创建这个表并插入默认数据的。为了程序更加智能化,我们需要首先判断表是否存在,如果不存在再创建表,为此写一个查看表是否存在的函数:
int check_table_isexist(char *table_name)
{
int ret;
char sql[1024];
char **sel_ret;
int row, col;
char *err = NULL;
ret = open_db();
if (ret != SQLITE_OK)
{
printf("open db error\n");
return -1;
}
sprintf(sql, "SELECT COUNT(*) FROM sqlite_master where type='table' and name='%s'", table_name);
if (SQLITE_OK != db_get_table(sql, &sel_ret, &row, &col, &err))
{
printf("check table %s error\n", table_name);
return -2;
}
if (row > 0)
{
int count = atoi(sel_ret[col]);
sqlite3_free_table(sel_ret);
return count;
}
sqlite3_free_table(sel_ret);
return 0;
}
注意读表操作后记得调用sqlite3_free_table释放资源,之后我们创建表的函数也要修改下:
static int create_db()
{
int ret;
char sql[1024] = {0};
ret = open_db();
if(ret != SQLITE_OK)
{
printf("open db error\n");
return -1;
}
// 检查表是否存在
if (check_table_isexist("TAB_CONFIG"))
{
printf("table POS_CONFIG has exist!\n");
return 0;
}
// 创建POS_CONFIG表
strcpy(sql, "create table TAB_CONFIG(CON_ADDR integer,CON_NO integer,CON_Info varchar(20));");
ret = sqlite3_exec(sql_db, sql, NULL,NULL,NULL);
if(ret != SQLITE_OK)
{
printf("CREATE table TAB_CONFIG error!\n");
return -2;
}
// 插入默认数据
sprintf(sql, "insert into TAB_CONFIG(CON_ADDR,CON_NO,CON_Info) values(1, 20,'%s')", "Hello world");
ret = db_exec(sql);
if (ret != SQLITE_OK)
{
printf("Table TAB_CONFIG insert data error!\n");
return -3;
}
return 0;
}
再写一个数据库初始化的封装函数:
int init_db()
{
if (SQLITE_OK == open_db())
return create_db();
return -1;
}
在db.h头文件中将这些函数导出:
#ifndef DB_H
#define DB_H
#include "sqlite3.h"
int init_db();
void close_db();
#endif
在main.c的主程序中写一个读取表的测试:
#include <stdio.h>
#include <string.h>
#include "db.h"
// 读取配置文件
int load_config()
{
int ret = 0;
char sql[200] = {0};
char **sel_ret;
int row, col;
char *err = NULL;
strcpy(sql, "select CON_ADDR,CON_NO,CON_Info from TAB_CONFIG");
ret = sqlite3_get_table(sql, &sel_ret, &row, &col, &err);
if(ret == SQLITE_OK)
{
if(row > 0) // 有数据
{
int dev_addr = atoi(sel_ret[col]);
int num = atoi(sel_ret[col+1]);
char info[20] = {0};
strcpy(info, sel_ret[col+2]);
printf("Read TAB_CONFIG data:\n");
printf("dev_addr=%d, num=%d, info=%s\n", dev_addr, num, info);
}
else
{
printf("@@Table TAB_CONFIG no data!\n");
}
}
else
{
printf("@@Read config param error!\n");
}
return ret;
}
int main(int argc,char* argv[])
{
if (init_db()
{
printf("database init failed!\n");
return -1;
}
load_config();
sleep(1);
close_db();
printf("programme has exit 0\n");
return 0;
}
为了程序在Linux系统下编译,得手动写个Makefile文件:
sqlite_test: sqlite3.o db.o main.o
gcc -o sqlite_test db.o main.o ./sqlite3/sqlite3.o -lpthread -ldl -lm
sqlite3.o: ./sqlite3/sqlite3.c
gcc -c ./sqlite3/sqlite3.c -o ./sqlite3/sqlite3.o
db.o: db.c db.h ./sqlite3/sqlite3.h
gcc -c db.c -o db.o -I ./sqlite3
main.o: main.c main.h ./sqlite3/sqlite3.h
gcc -c main.c -o main.o -I ./sqlite3
.PHONY: clean
clean:
rm -rf *.o ./sqlite3/*.o *~ sqlite_test
Makefile具体规则这里就不介绍了,但要注意文件目录的结构和依赖关系,因为程序的目录结构如下:
所以编译sqlite3时要写全目录./sqlite3/sqlite3.o,而且引用sqlite3.h时也要写全目录./sqlite3/sqlite3.h。如果是嵌入式Linux使用的话,需要把Makefile中的所有gcc替换为arm-linux-gcc即可,但前提是得先定义交叉编译器的环境变量,为保险起见,编译前查看一下版本信息:
这样说明交叉编译器的环境变量设置成功了。还有个问题,PC和嵌入式Linux编译总得切换Makefile,能不能写一个Makefile文件呢?答案是肯定的,仿照嵌入式惯例,只需定义一个编译变量CC,只需make时给它赋值即可:
默认是gcc,如果给ARCH赋值arm的话,CC变量就变为arm-linux-gcc:
这下好了Makefile文件,可以编译两种结果了,运行一下吧,执行结果如下:
从打印信息看,说明读取表数据的内容是正确的了。
更多推荐
所有评论(0)