赞
踩
在嵌入式领域中,数据库也是必备的技能之一,本期主要分享的是sqlite3、sqlite3命令以及aqlite3数据库API应用,那么就让我们认识一下数据库以及数据库的使用吧!
数据库就是用来高效的管理数据的一种工具,能够实现对数据的增删改查,主要应用场景有:
(1)大批量数据管理
(2)提高查找数据效率
1、关系型数据库
键值:在数据库中唯一能够找到一条数据标志(不允许重复),是一对一的;下面列举一些常见的数据库:
Oracle、DB 大型数据库
MySql、SqlServer 中型数据库
Sqlite 小型数据库
Sqlite特点:
可以实现大数据量的管理
读写速度慢
2、非关系型数据库
Redis 内存数据库
NoSql
特点:
读写速度快(1s实现读写上万次)
(1)文件名
filename.db
(2)表
一系列数据的集合
格式:分为不同的列
打开数据库文件 sqlite3 filename.db
(1).headers on|off
打开/关闭表字段的显示
(2).mode + colunm
设置显示格式
(3).quit
退出
(4).read filename.sql
加载filename.sql中的语句
(5).tables
查看文件中所有的表
所有的数据库中均支持SQL语句
(1)create table CREATE TABLE table_name( column1 datatype PRIMARY KEY, column2 datatype, column3 datatype, ..... columnN datatype, ); 比如创建一个表:create table info (学号 interger primary key, 姓名 char (255), 性别 char(32), 年龄 interger); 创建了一张名字为info的新表; (2)insert into INSERT INTO TABLE_NAME VALUES (value1, value2, value3,...valueN); 比如向表中添加成员:insert into info values (1001, 'zhangsan', 'm', 12); (3)select SELECT column1, column2, columnN FROM table_name; 比如查看表内的所有信息: select * from info; (4)where 作用:查找的时候进行筛选 比如: select * from info where 学号 = 1001; 在info这张表中查找学号等于1001的这个学生; (5)delete from DELETE FROM table_name WHERE [condition]; 作用:删除信息 比如:delete from info where 学号 = 1001;删除info表中学号等于1001的这个学生的所有信息; (6)update UPDATE table_name SET column1 = value1, column2 = value2...., columnN = valueN WHERE [condition]; 作用:修改某个信息 比如:update info set 学号 = 1001 where 学号 = 1003;把学号为1003的学生的学号修改为1001; (7)order SELECT column-list FROM table_name [WHERE condition] [ORDER BY column1, column2, .. columnN] [ASC | DESC]; (8)drop table 作用:删除表 比如:drop table info; 删除名字为info的这张表; 多表联合查询 (1)CROSS JOIN 交叉连接 例子:把info和lesson两张表一起查找,把info的姓名修改为名字,课程名修改为科目;(ab两张表各部分做拼接) sqlite> select info.姓名 as 名字, lesson.课程名 as 科目 ...> from info cross join lesson; (2)INNER JOIN 内连接(左边有的右边有的都显示,左边有的右边没有的也显示,但是右边的部分是空的) SELECT ... FROM table1 [INNER] JOIN table2 ON conditional_expression ... 例子:在info和score两张表的相同部分中进行查找 sqlite> select info.姓名 as 名字, score.成绩 as 分数 ...> from info inner join score on info.学号 = score.学号; (3)OUTER JOIN 左连接(以左边为基准) sqlite> select info.姓名,score.成绩 ...> from info left outer join score on info.学号 = score.学号; (4)三表联合查询 sqlite> select info.姓名, lesson.课程名, score.成绩 ...> from info left outer join score on info.学号 = score.学号 ...> left outer join lesson on score.课程号 = lesson.课程号 ...> order by 成绩 desc;
(1)sqlite3_open
int sqlite3_open(
const char *filename, /* Database filename (UTF-8) */
sqlite3 **ppDb /* OUT: SQLite db handle */
);
功能:打开数据库文件并返回一个句柄
参数:
filename:数据库文件路径
ppDb:存放句柄空间的首地址
返回值:
成功返回SQLITE_OK
失败返回错误码
(2)sqlite3_exec int sqlite3_exec( sqlite3*, /* An open database */ const char *sql, /* SQL to be evaluated */ int (*callback)(void*,int,char**,char**), /* Callback function */ void *, /* 1st argument to callback */ char **errmsg /* Error msg written here */ ); 功能: 加载一条SQL语句 参数: sqlite3*:数据库文件句柄 sql:SQL语句字符串空间首地址 callback:回调函数(select时使用,这个函数就是查到之后做什么,做的就是callback这个函数) void*:给回调函数传参(select时使用) errmsg:存储出错信息空间的首地址 返回值: 成功返回SQLITE_OK 失败返回错误码 注意: (1)sql的命令当编程创建数据库文件时时可能会重复创建,所以在前面一般加上if not exists(例:"create table if not exists info (学号 interger primary key, 姓名 char(255), 性别 char(32), 年龄 interger);") (2)每找到一次符合的数据会调用一次callback; (2) int (*callback)(void *arg,int n,char **pcontent ,char **ptitle); 该函数返回非0时会导致sqlite3_exec ();函数出错; arg:sqlite3_exec中的第四个参数,可用于主函数传参 n:找到数据的列数 pcontent:指向内容每一列字符串空间首地址的指针数组(指向第一条数据的第一行的第一个元素) ptitle:指向标题每一列字符串空间首地址的指针数组(姓名性别年龄等)
(3)sqlite3_close
int sqlite3_close(sqlite3*);
功能:
关闭数据库句柄
(4)const char *sqlite3_errmsg(sqlite3*);
功能:获得sqlite3错误原因
(5)void sqlite3_free(void*);
功能:释放申请的空间(出错时,出错信息打印完毕后,需要释放)
本次分享的这个小练习虽然听上去比较简单,但是用到的技术点也是比较多的,那么带大家仔细来看一下;
首先呢还是头文件部分啦:
#ifndef __HEAD_H__
#define __HEAD_H__
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "sqlite3.h"
#endif
接下来看一下主程序部分:
主程序实现的功能是循环接收用户需要查找的单词,进而在数据库中查找单词,当用户输入.quit时APP结束;
int main(int argc, const char *argv[]) { char word[32] = {0}; char mean[1024] = {0}; int ret = 0; // writeToSql(); //此函数只运行一次,因为我们只需要把所有单词存入数据库一次即可,后续只进行查找即可 while (1) { fgets(word, sizeof(word), stdin); //用户输入单词 word[strlen(word) - 1] = 0; if (!strcmp(word, ".quit")) //用户输入.quit时退出 { break; } searchWord(word, mean); //在数据库中查找单词 if (0 == flag) { printf("not found!\n"); } if (1 == flag) { printf("===============================\n"); printf("word:%s\nmean:%s\n", word, mean); } } return 0; }
下面来看一下单词和含义是如何写入数据库的:
int writeToSql(void) { FILE *fp = NULL; char tmpbuff[1024] = {0}; char *ptmp = NULL; sqlite3 *pdb = NULL; int ret = 0; char word[32] = {0}; char mean[1024] = {0}; char cmdbuf[1024] = {0}; fp = fopen("./dictionary.txt", "r"); //打开存放单词和含义的文本文件 if (NULL == fp) { perror("fail to fp"); return -1; } ret = sqlite3_open("./dictionary.db", &pdb); //打开数据库 if (SQLITE_OK != ret) { fprintf(stderr, "%s", sqlite3_errmsg(pdb)); sqlite3_free(pdb); return -1; } sprintf(cmdbuf, "create table if not exists info (编号 integer primary key, 单词 char(32), 含义 char(1024));");//这里注意一定设置一个主键值(哪怕不用),防止因为单词重复出现的诸多问题 ret = sqlite3_exec(pdb, cmdbuf, NULL, NULL, NULL); //创建表 if (SQLITE_OK != ret) { fprintf(stderr, "%s", sqlite3_errmsg(pdb)); sqlite3_free(pdb); sqlite3_close(pdb); return -1; } while (1) { memset(word, 0, sizeof(word)); memset(mean, 0, sizeof(mean)); memset(tmpbuff, 0, sizeof(tmpbuff)); ptmp = fgets(tmpbuff, sizeof(tmpbuff), fp); //从文本中读取一行数(也就是读取一个单词以及它的含义) if (NULL == ptmp) { break; } strcpy(word, strtok(tmpbuff, " ")); //按照空格进行分割 ptmp = strtok(NULL, "\n"); //剩下的按照\n进行分割 while (*ptmp == ' ') //分割后的前面也是空格,所以把前面的空格必须去掉 { ++ptmp; } strcpy(mean, ptmp); //获得含义 // printf("word:%s\nmean:%s\n", word, mean); memset(cmdbuf, 0, sizeof(cmdbuf)); sprintf(cmdbuf, "insert into info values(NULL, \"%s\", \"%s\");", word, mean); //向数据库中插入单词和含义,一定注意转义字符的表示(也要注意上面创建表格的注意事项) ret = sqlite3_exec(pdb, cmdbuf, NULL, NULL, NULL); if (SQLITE_OK != ret) { fprintf(stderr, "%s", sqlite3_errmsg(pdb)); sqlite3_free(pdb); sqlite3_close(pdb); return -1; } } fclose(fp); sqlite3_close(pdb); return 0; }
最后呢我们来看一下如何实现查找功能:
注意:这里呢我用了一个flag,每次循环开始置为0,只要找到这个单词那么就使其为1;
int flag = 0; int callback(void *arg, int n, char **pcontent, char **ptitle) { flag = 1; char *ptmp = arg; strcpy(ptmp, pcontent[2]); return 0; } int searchWord(const char *word, char *mean) { sqlite3 *pdb = NULL; char cmdbuf[1024] = {0}; int ret = 0; ret = sqlite3_open("./dictionary.db", &pdb); //打开数据库文件 if (SQLITE_OK != ret) { fprintf(stderr, "%s", sqlite3_errmsg(pdb)); sqlite3_free(pdb); return -1; } memset(cmdbuf, 0, sizeof(cmdbuf)); sprintf(cmdbuf, "select * from info where 单词 = \"%s\";", word); ret = sqlite3_exec(pdb, cmdbuf, callback, mean, NULL); //查找单词 if (SQLITE_OK != ret) { fprintf(stderr, "%s", sqlite3_errmsg(pdb)); sqlite3_free(pdb); return -1; } sqlite3_close(pdb); //关闭数据库 return 0; }
上述就是一个简单的电子小词典的功能,那么这个小项目就使得我们对数据库的API接口有了进一步的认识,如果大家感兴趣可以尝试使用TCP网络编程实现一个在线词典的功能,并且加上多任务并发,可以尝试做一下哦,我后期也会出这个小项目,敬请期待吧,各位小伙伴们!
来展示一下词典的运行结果吧:
1.一定不要觉得自己理解了,看会了,就觉得简单不去动手做,这样会大大降低对知识点的巩固,可能根本对这个知识点没有自己想象中的那么了解,必须通过实际操作,动手才能知道自己的问题在哪里;
2.本期分享主要还是对于sqlite3、sqlite3命令以及sqlite3_open、sqlite3_exec、sqlite3_close数据库API的应用,希望各位小伙伴们动起手来,一起加油进步!!!
最后,各位小伙伴们如果喜欢我的分享可以点赞收藏哦,你们的认可是我创作的动力,一起加油!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。