Linux网络编程05-sqlite3数据库

一、数据库介绍

① 数据库:能够对大批量数据进行增删改查管理的软件
② 数据库分类
(1)关系型数据库

  • 将数据存放在文件中,将复杂的数据结构简化为二维表格形式。
  • 大型:Oracle、DB2
  • 中型:MySql、SQLServer
  • 小型:Sqlite

(2)非关系型数据库

  • 将数据存放在内存中(内存数据库),以键值对存储,且结构不固定。
  • Redis、 Nosql、MongoDB

③ 嵌入式数据库:sqlite3

  • 开源免费, c语言开发
  • 代码量少,2万行左右,总大小10M以内
  • 文件型数据库,可以移动
  • 数据容量最大2T

④ 安装SQlite3数据库

cpp 复制代码
1.在线安装
    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 创建数据库

cpp 复制代码
sqlite3 DatabaseName.db //创建一个名为DatabaseName.db数据库

3.2 create table语句(创建表)

bash 复制代码
create 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 语句(插入表)

bash 复制代码
insert 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语句(查表)

bash 复制代码
select 列名称1, 列名称2, ... from 表名;
示例:
select * from student;

3.5 where子句

bash 复制代码
SELECT 列名称 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语句(改表中信息)

bash 复制代码
UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值;
示例:
update student set score=91 where name="赵五";

3.7 delete语句(删除表中信息)

bash 复制代码
delete from 表名称 where 列名称 = 值;
示例:
delete from student where name = "王二";

3.8 order by子句(顺序显示)

bash 复制代码
selete * 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 语句(删除一张表)

bash 复制代码
drop table 表名称;
示例:
drop table student;

3.10 datetime语句

bash 复制代码
datetime('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(多表联合查询)

bash 复制代码
1. 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

cpp 复制代码
int sqlite3_open( const char *filename, /* Database filename (UTF-8) */
    sqlite3 **ppDb /* OUT: SQLite db handle */);
功能:打开数据库文件获得操作数据库文件的句柄
     如果数据库存在,则打开;不存在,则创建
参数:
    filename:数据库文件名/路径
    ppDb:存放数据库句柄空间的首地址
返回值:
    成功返回SQLITE_OK

4.2 sqlite3_errmsg

cpp 复制代码
const char *sqlite3_errmsg(sqlite3 *pdb);
功能: 获得出错原因

4.3 sqlite3_exec

cpp 复制代码
int 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

cpp 复制代码
void sqlite3_free(void *perrmsg);
功能:释放保存出错信息的空间

4.5 sqlite3_close

cpp 复制代码
int 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;
}
相关推荐
青禾8371 小时前
一文入门 MySQL + MongoDB + Redis:三大数据库核心知识
数据库·mysql·mongodb
Huangjin007_1 小时前
【Linux 系统篇(十七)】进程(五) :进程切换、O(1) 调度算法
linux·运维·服务器
努力努力再努力wz1 小时前
【Redis入门系列】:从 RESP 协议到 redis-plus-plus:Redis 客户端编程与 C++ 接口设计
开发语言·数据库·c++·redis·分布式·缓存·架构
weixin_464307631 小时前
linux虚拟机断网
linux·运维·服务器
志栋智能1 小时前
凌晨3点的告警,如何用AI在5分钟内完成定界?
运维·服务器·数据库·人工智能·自动化
G.E.M.小白1 小时前
【SQLite3 数据库】从安装、SQL 操作到 C/C++ API 实战
数据库·oracle·sqlite3
Htr_1 小时前
GPT-6 Astra 使用指南:OpenAI 首个“关键级“网络安全模型的完整上手手册
网络·gpt
λqaq71 小时前
Docker 容器入门基础:Cloud Studio 在线 Linux 环境上手
linux·运维·docker
神明不懂浪漫1 小时前
【第一章】MySQL简介
数据库·经验分享·笔记·mysql·oracle