一、数据库介绍
① 数据库:能够对大批量数据进行增删改查管理的软件
② 数据库分类
(1)关系型数据库
- 将数据存放在文件中,将复杂的数据结构简化为二维表格形式。
- 大型:Oracle、DB2
- 中型:MySql、SQLServer
- 小型:Sqlite
(2)非关系型数据库
- 将数据存放在内存中(内存数据库),以键值对存储,且结构不固定。
- Redis、 Nosql、MongoDB
③ 嵌入式数据库:sqlite3
- 开源免费, c语言开发
- 代码量少,2万行左右,总大小10M以内
- 文件型数据库,可以移动
- 数据容量最大2T
④ 安装SQlite3数据库
cpp1.在线安装 sudo apt-get install sqlite3 (SQLite 的命令行工具 + 运行时库) sudo apt-get install libsqlite3-dev (SQLite 的开发库包) 2.源码安装 1.sqlite-autoconf-3080403源代码.tar.gz拷贝到Ubuntu系统Desktop目录中 2.tar -zxvf sqlite-autoconf-3080403源代码.tar.gz 3.cd sqlite-autoconf-3080403 4../configure // 生成makefile 5.make // 编译源码 6.sudo make install // 安装 3.数据库维护命令 安装可视化工具 sudo apt-get install sqlitebrowser sqlitebrowser xxx.db Navicat Sqlite3 Windows下图形操作接口
二、sqlite3 操作指令
bash.help 查看sqlite3支持的相关命令 .quit 退出sqlite3数据库 .tables 查看表名称,查看数据库中的所有表 .databases 列出附加数据库的名称和文件 .headers on/off 开启关闭列名称显示 .mode column 设置数据显示的形式,以左对齐列宽显示数据 .schema tablename 查看表创建的信息,查看tablename创建时的SQL语句(表的结构) .width 设置显示的宽度SQLite 教程:https://www.runoob.com/sqlite/sqlite-tutorial.html
三、SQL语句
① 支持数据类型(SQLite 存储类)
存储类 描述 NULL 值是一个 NULL 值。 INTEGER 值是一个带符号的整数,根据值的大小存储在 1、2、3、4、6 或 8 字节中。(int) REAL 值是一个浮点值,存储为 8 字节的 IEEE 浮点数字。(double、float) TEXT 值是一个文本字符串(char 字符串),使用数据库编码(UTF-8、UTF-16BE 或 UTF-16LE)存储。 BLOB 值是一个 blob 数据,完全根据它的输入存储。
3.1 创建数据库
cppsqlite3 DatabaseName.db //创建一个名为DatabaseName.db数据库
3.2 create table语句(创建表)
bashcreate table 表名 (列名称1 数据类型1, 列名称2 数据类型2, ...); 表不存在,则创建,存在不创建 create table if not exists 表名称(列名称1 数据类型,列名称2 数据类型,列名称3 数据类型,....); 设置主键值自动增长列 create table 表名称(id INTEGER PRIMARY KEY AUTOINCREMENT, 类名称 数据类型, ...); 示例: create table student (id integer, name text, sex text, age integer, score integer);
3.3 insert into 语句(插入表)
bashinsert into 表名 values (值1, 值2, ...); 示例: insert into student values (1, "张三", "男", 18, 90); insert into student values (3, "王二", NULL, NULL, NULL); insert into student (id, name, sex) values (4, "赵五", "男");
3.4 select语句(查表)
bashselect 列名称1, 列名称2, ... from 表名; 示例: select * from student;
3.5 where子句
bashSELECT 列名称 FROM 表名称 WHERE 列 运算符 值; 1. 匹配条件 = 等于 <> 、!= 不等于 > 大于 < 小于 >= 大于等于 <= 小于等于 and、or BETWEEN 在某个范围内 LIKE 搜索某种模式 百分号(%)代表零个、一个或多个数字或字符。 下划线(_)代表一个单一的数字或字符。这些符号可以被组合使用。 示例: select name,score from student where name like "赵%"; //模糊查找 select name from student where score >= 90; select name,score from student where name like "赵%" and score > 95;
3.6 update语句(改表中信息)
bashUPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值; 示例: update student set score=91 where name="赵五";
3.7 delete语句(删除表中信息)
bashdelete from 表名称 where 列名称 = 值; 示例: delete from student where name = "王二";
3.8 order by子句(顺序显示)
bashselete * form 表名称 order by 列名 ASC; //升序查询 selete * form 表名称 order by 列名 DESC; //降序查询 示例: select name,score from student where sex="男" order by score desc; select * from class1 order by score ASC; 升序查询 select * from class1 order by score DESC;降序查询
3.9 drop table 语句(删除一张表)
bashdrop table 表名称; 示例: drop table student;
3.10 datetime语句
bashdatetime('now', '+8 hours'); select datetime('now', '+8 hours'); 查询当前东八区时间 示例: insert into class3 values(1, 'zhangsan', 99, datetime('now', '+8 hours')); insert into class3 values(2, 'lisi', 100, datetime('now', '+8 hours')); insert into class3 values(3, 'wanger', 98, datetime('now', '+8 hours'));
3.11 joins(多表联合查询)
bash1. cross join 交叉连接 sqlite> select 学生信息.姓名 as 姓名, 课程信息.名称 as 课程, 课程信息.学 分 as 学分 from ...> 学生信息 cross join 课程信息; 2. inner join 内连接 sqlite> select 学生信息.姓名 as 姓名, 成绩信息.成绩 as 成绩 from ...> 学生信息 inner join 成绩信息 on 学生信息.ID = 成绩信息.学生ID; sqlite> select 学生信息.姓名 as 姓名, 课程信息.名称 as 课程, 成绩信息.成 绩 as 成绩 from ...> 学生信息 inner join 成绩信息 on 学生信息.ID = 成绩信息.学生ID ...> inner join 课程信息 on 成绩信息.课程ID = 课程信息.ID; 3. outer join 外连接 sqlite> select 学生信息.姓名 as 姓名,成绩信息.成绩 as 成绩 from ...> 学生信息 left outer join 成绩信息 on 学生信息.ID = 成绩信息.学 生ID;
四、sqlite数据库编程c/c++接口
编程框架:打开数据库 --> 读写数据库(增,删,改,查)--> 关闭数据库
sqlite3官网: SQLite Home Page
sqlite3.c
sqlite3.h
编译时要加:-lsqlite3
4.1 sqlite3_open
cppint sqlite3_open( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb /* OUT: SQLite db handle */); 功能:打开数据库文件获得操作数据库文件的句柄 如果数据库存在,则打开;不存在,则创建 参数: filename:数据库文件名/路径 ppDb:存放数据库句柄空间的首地址 返回值: 成功返回SQLITE_OK
4.2 sqlite3_errmsg
cppconst char *sqlite3_errmsg(sqlite3 *pdb); 功能: 获得出错原因
4.3 sqlite3_exec
cppint sqlite3_exec( sqlite3 *pdb, /* An open database*/ const char *sql, /* SQL to be evaluated */ int (*callback)(void*,int,char**,char**), /* Callback function */ void *arg, /* 1st argument to callback */ char **errmsg /* Error msg written here */ ); 功能:在数据库中执行一条SQL语句 参数: pdb:数据库句柄 sql: 要加载的SQL语句空间首地址 callback:select语句时使用的回调函数(对找到的数据处理的方法) arg: 对回调函数的传参(只有select时使用) errmsg:错误信息存放空间的首地址 返回值: 成功返回SQLITE_OK 失败返回错误码 回调函数类型: int callbackfun(void *arg, int colnum, char **pcontent, char **ptitle); 功能:select查询时触发的回调函数 参数:char** 两个指针数组 arg : sqlite3_exec传递的第四个参数 column :查询到数据的列数,select生成的表的列数 pcontent:列内容指针数组 ptitle:列名称指针数组 返回值: 成功返回0 如果不返回0,sqlite3_exec会报错 注意: 1.回调函数查询到几行数据就执行几次;该回调函数会随着select每找到一个数据就会被调用一次 2.回调函数必须要返回值,否则sqlite3_exec调用失败; 3.如果select找不到匹配数据,则一次回调都不会调用 ; 4.数据库中查出的数据均为字符串
4.4sqlite3_free
cppvoid sqlite3_free(void *perrmsg); 功能:释放保存出错信息的空间
4.5 sqlite3_close
cppint sqlite3_close(sqlite3 *pdb); 功能:关闭数据库连接
实列:
cpp#include "sqlite3.h" #include <stdio.h> typedef struct student { char name[32]; char sex[8]; int age; int score; }stu_t; /******************************************** * 功能:callbackfun * 参数: * arg:sqlite3_exec传递的参数 * colnum:select生成的表的列数 * ptitle:列名称指针数组 * pcontent:列内容指针数组 * 返回值: * 成功返回0 * 如果不返回0,sqlite3_exec会报错 * 注意事项: * 1.该回调函数会随着select每找到一个数据就会被调用一次 * 2.如果select找不到匹配数据,则一次回调都不会调用 ********************************************/ int callbackfun(void *arg, int colnum, char **pcontent, char **ptitle) { int i = 0; for (i = 0; i < colnum; i++) { printf("ptitle[%d] = %s\t\t", i, ptitle[i]); } printf("\n"); for (i = 0; i < colnum; i++) { printf("pcontent[%d] = %s\t\t", i, pcontent[i]); } printf("\n"); return 0; } int main(void) { sqlite3 *pdb = NULL; int ret = 0; char cmd[1024] = {0}; char *perrmsg = NULL; stu_t s[3] = { {"张三", "男", 17, 90}, {"李四", "女", 16, 80}, {"王二", "男", 15, 40}, }; int i = 0; ret = sqlite3_open("student.db", &pdb); if (ret != SQLITE_OK) { fprintf(stderr, "sqlite3_open failed:%s\n", sqlite3_errmsg(pdb)); return -1; } #if 0 sprintf(cmd, "create table if not exists student (ID integer primary key asc, name text, sex tex, age integer, score integer);"); ret = sqlite3_exec(pdb, cmd, NULL, NULL, &perrmsg); if (ret != SQLITE_OK) { fprintf(stderr, "sqlite3_exec failed:%s\n", perrmsg); sqlite3_free(perrmsg); return -1; } for (i = 0; i < 3; i++) { sprintf(cmd, "insert into student values (NULL, \"%s\", \"%s\", %d, %d);", s[i].name, s[i].sex, s[i].age, s[i].score); ret = sqlite3_exec(pdb, cmd, NULL, NULL, &perrmsg); if (ret != SQLITE_OK) { fprintf(stderr, "sqlite3_exec failed:%s\n", perrmsg); sqlite3_free(perrmsg); return -1; } } #endif sprintf(cmd, "select * from student;"); ret = sqlite3_exec(pdb, cmd, callbackfun, NULL, &perrmsg); if (ret != SQLITE_OK) { fprintf(stderr, "sqlite3_exec failed:%s\n", perrmsg); sqlite3_free(perrmsg); return -1; } sqlite3_close(pdb); return 0; }
cpp//Makefile OBJ:=a.out OBJS+=main.o OBJS+=sqlite3.o LDFLAGS:=-lpthread -ldl $(OBJ):$(OBJS) gcc $^ -o $@ $(LDFLAGS) %.o:%.c gcc -c $^ -o $@ .PHONY: clean: rm $(OBJ) distclean: rm *.o rm $(OBJ)
练习:将dict.txt文件中的单词和含义插入到数据库中,从终端输入单词,利用代码在数据库中查找其对应的含义并打印在终端
cpp#include "sqlite3.h" #include <stdio.h> #include <string.h> #include <fcntl.h> #include <unistd.h> typedef struct data { char *pmean; int flag; }data_t; int CreateWordDB(const char *pDbName, const char *pFileName) { sqlite3 *pdb = NULL; FILE *fp = NULL; char tmpbuff[4096] = {0}; char *pret = NULL; char *ptmp = NULL; char cmd[1024] = {0}; char *perrmsg = NULL; int ret = 0; long tlen = 0; long clen = 0; //打开数据库 ret = sqlite3_open(pDbName, &pdb); if (ret != SQLITE_OK) { fprintf(stderr, "sqlite3_open failed:%s\n", sqlite3_errmsg(pdb)); return -1; } //创建表 sprintf(cmd, "create table if not exists 单词列表 (ID integer primary key asc, 单词 text, 含义 text);"); ret = sqlite3_exec(pdb, cmd, NULL, NULL, &perrmsg); if (ret != SQLITE_OK) { fprintf(stderr, "fail to sqlite3_exec:%s\n", perrmsg); sqlite3_free(perrmsg); return -1; } //打开文件 fp = fopen(pFileName, "r"); if (NULL == fp) { perror("fail to fopen"); return -1; } fseek(fp, 0, SEEK_END); tlen = ftell(fp); rewind(fp); sprintf(cmd, "BEGIN TRANSACTION;"); ret = sqlite3_exec(pdb, cmd, NULL, NULL, &perrmsg); if (ret != SQLITE_OK) { fprintf(stderr, "fail to sqlite3_exec:%s\n", perrmsg); sqlite3_free(perrmsg); return -1; } while (1) { //读取一行 pret = fgets(tmpbuff, sizeof(tmpbuff), fp); if (NULL == pret) { break; } //拆分获得单词 ptmp = tmpbuff; while (*ptmp != '\0' && *ptmp != ' ') { ptmp++; } *ptmp = '\0'; //拆分获得含义 ptmp++; while (*ptmp != '\0' && ' ' == *ptmp) { ptmp++; } //将改行单词和含义插入数据库中 sprintf(cmd, "insert into 单词列表 values (NULL, \"%s\", \"%s\");", tmpbuff,ptmp); ret = sqlite3_exec(pdb, cmd, NULL, NULL, &perrmsg); if (ret != SQLITE_OK) { fprintf(stderr, "fail to sqlite3_exec:%s\n", perrmsg); sqlite3_free(perrmsg); return -1; } clen = ftell(fp); printf("已加载:%.2lf%%\r", ((double)clen / (double)tlen) * 100.0); fflush(stdout); } sprintf(cmd, "END TRANSACTION;"); ret = sqlite3_exec(pdb, cmd, NULL, NULL, &perrmsg); if (ret != SQLITE_OK) { fprintf(stderr, "fail to sqlite3_exec:%s\n", perrmsg); sqlite3_free(perrmsg); return -1; } fclose(fp); sqlite3_close(pdb); printf("加载完成 \n"); return 0; } int callbackfun(void *arg, int colnum, char **pcontent, char **ptitle) { data_t *pdata = arg; strcpy(pdata->pmean, pcontent[0]); pdata->flag = 1; return 0; } int FindWordMean(const char *pDbName, char *pword, char *pmean) { int ret = 0; sqlite3 *pdb = NULL; char cmd[1024] = {0}; char *perrmsg = NULL; int IsExist = 0; data_t TmpData; //打开数据库 ret = sqlite3_open(pDbName, &pdb); if (ret != SQLITE_OK) { fprintf(stderr, "sqlite3_open failed:%s\n", sqlite3_errmsg(pdb)); return -1; } TmpData.pmean = pmean; TmpData.flag = 0; sprintf(cmd, "select 含义 from 单词列表 where 单词=\"%s\";", pword); ret = sqlite3_exec(pdb, cmd, callbackfun, &TmpData, &perrmsg); if (ret != SQLITE_OK) { fprintf(stderr, "fail to sqlite3_exec:%s\n", perrmsg); sqlite3_free(perrmsg); return -1; } IsExist = TmpData.flag; sqlite3_close(pdb); return IsExist; } int main(void) { int ret = 0; char word[256] = {0}; char mean[4096] = {0}; if (access("dict.db", F_OK)) { CreateWordDB("dict.db", "dict.txt"); } printf("请输入单词:\n"); gets(word); ret = FindWordMean("dict.db", word, mean); if (ret) { printf("含义:%s\n", mean); } else { printf("%s单词不存在\n", word); } return 0; }