第七篇 嵌入式数据库SQLite

发布于:2023-02-13 ⋅ 阅读:(801) ⋅ 点赞:(0)

目录

 一、SQLite数据库简介

 二、安装SQLite3数据库(ubuntu20.04下)

方式一:直接下载安装

方式二:源码包编译安装

三、SQLite基础操作(Linux)

1.SQLite下的点命令

🔖打开/创建数据库.open

🔖查看数据库中所有表.table

🔖输出模式.mode 

🔖帮助信息.help

2.SQL基本语句操作表

🔖创建表、删除表

🔖向表中增加数据(增)

🔖删除表中的数据(删)

🔖修改表中的数据(改)

🔖查询表中的数据(查)

四、SQLite的C编程

1.打开数据库sqlite3_open

2.关闭数据库sqlite3_close

3.执行SQL语句sqlite3_exec

4.(重要)回调函数callback 

五、C操作SQLite数据库

1.Demo1.c(执行select * from student.db)

2.Demo2.c(在demo1的基础上,将数据存在链表中)

3.Demo3.c(创建表,并插入数据)


本篇浅学嵌入式数据库SQLite,关于SQLite的详细教程可参考:SQLite教程丨菜鸟教程

 一、SQLite数据库简介

        SQLite是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的SQL 数据库引擎,也称嵌入式数据库。它是一个零配置的数据库,这意味着与其他数据库不一样,不需要在系统中配置。就像其他数据库,SQLite 引擎不是一个独立的进程,作为应用程序一部分运行,可以按应用程序需求进行静态或动态连接。SQLite 直接访问其存储文件

(MySQL需要运行服务器,需要服务器和客户端通过网络交互)

SQLite

MySQL

优点

  • 基于文件,易于设置和使用
  • 适合基础开发和测试。
  • 使用标准SQL语法(仅有微小更改)
  • 良好的安全功能,易于扩展
  • 适用于大型数据库
  • 速度和性能良好
  • 提供较为全面的用户管理和多种访问控制

缺点

  • 缺乏用户管理和安全功能
  • 不适合应用在大型数据库
  • 不易于扩展,无法定制
  • 非零配置数据库
  • 与传统SQL语法略不同

此外,基于嵌入式的数据库还有:Firebird、Berkeley DB、eXtreme DB

🔖SQLite是关系型数据库,体积小支持ACID事务

🔖Firebird是关系型数据库,支持存储过程,SQL兼容

🔖Berkeley DB没有数据库服务器概念,程序直接链接到应用程序

🔖eXtreme DB内存数据库,运行速度快

 二、安装SQLite3数据库(ubuntu20.04下)

方式一:直接下载安装

(可能会出现安装不了SQLite3,可以改用第二种安装)

root@ubuntu:~# sudo apt-get install sqlite3

方式二:源码包编译安装

SQLite3官网下载链接

这里下载的是最新版sqlite-autoconf-3390100.tar.gz

(从官网下载好SQLite3的压缩包后,解压后开始进行编译和安装)

Step1:解压源码包 tar -zxvf sqlite-autoconf-3390100.tar.gz 
Step2:进入源码包主目录 cd sqlite-autoconf-3390100/
Step3:配置安装路径 ./configure --prefix=/usr/local
Step4:编译 make
Step5:安装 make install

大部分第三方源码包的安装方法

三、SQLite基础操作(Linux)

1.SQLite下的点命令

(SQLite下嵌入了简单实用的命令,不同于SQL语句,这些命令不以;结尾。提供了查看、创建数据库等操作的功能,如.open student.db打开student数据库。这样的命令也称为点命令)

🔖打开/创建数据库.open

.open+databasename.db   打开数据库,不存在就创建

.database  查看所有数据库信息

sqlite> .open student.db
sqlite> .database
main: /root/student.db r/w
sqlite> 

🔖查看数据库中所有表.table

sqlite> .table
stu_Info      teacher_info
sqlite> 

🔖输出模式.mode 

.mode column    显示表头字段

sqlite> .mode column
sqlite> select * from stu_Info;
ID  name      age  register
--  --------  ---  --------
1   zhangsan  18           
2   lisi      19   1  

🔖帮助信息.help

sqlite> .help
.archive ...             Manage SQL archives
.auth ON|OFF             Show authorizer callbacks
.echo on|off             Turn command echo on or off
sqlite> 
(这里只截取了几条 .help会列出所有点命令的使用帮助)

2.SQL基本语句操作表

🔖创建表、删除表

例:创建学生信息表,包含字段有学号ID、姓名name、年龄age、注册信息register

sqlite> create table stu_Info (ID int,name char,age int,register bool);
sqlite>

🔖向表中增加数据(增)

例1:向表中写入学生王五(3,19,已注册)的数据

sqlite> insert into stu_Info values(3,"wangwu",19,1);
sqlite> select * from stu_Info;
ID  name      age  register
--  --------  ---  --------
1   zhangsan  18           
2   lisi      19   1       
3   wangwu    19   1       
sqlite>

例2:向表中写入学生小明(已知小明的学号4)的数据

sqlite> insert into stu_Info(ID,name) 
values(4,"xiaoming");
sqlite> select * from stu_Info;
ID  name      age  register
--  --------  ---  --------
1   zhangsan  18           
2   lisi      19   1       
3   wangwu    19   1       
4   xiaoming               
sqlite> 

🔖删除表中的数据(删)

例:删除学生信息表中没有注册的学生信息

sqlite> delete from stu_Info where register is NULL 
sqlite> select * from stu_Info;
ID  name    age  register
--  ------  ---  --------
2   lisi    19   1       
3   wangwu  19   1       
sqlite> 

🔖修改表中的数据(改)

例:将wangwu的年龄修改为20岁

sqlite> update stu_Info set age=20 where name="wangwu";
sqlite> select  * from stu_Info;
ID  name    age  register
--  ------  ---  --------
2   lisi    19   1       
3   wangwu  20   1       
sqlite> 

🔖查询表中的数据(查)

例1:查询表中所有学生数据

sqlite> .mode column
sqlite> select * from stu_Info;
ID  name      age  register
--  --------  ---  --------
1   zhangsan  18           
2   lisi      19   1  

例2:查询表中所有学生的姓名和年龄

sqlite> select name,age from stu_Info;
name      age
--------  ---
zhangsan  18 
lisi      19 
sqlite> 

例3:查询未注册的学生信息

sqlite> select * from stu_Info where register is NULL;
ID  name      age  register
--  --------  ---  --------
1   zhangsan  18           
sqlite> 

四、SQLite的C编程

        在C/C++程序中使用SQLite之前,需要确保机器上已经有SQLite库。在编译程序时需要加选项-lsqlite3链接到SQLite的库。

1.打开数据库sqlite3_open

✒️函数原型int sqlite3_open(const char *zFilename,sqlite3 **ppDb);

✒️参数说明:①zFilename:打开的数据库名(如:student.db,不为NULL将以附加的方式打开该数据库,如果为NULL,会在RAM中创建一个只在当前会话有效的临时内存数据库。

②ppDb:指向操作数据库的句柄的地址

✒️返回值:0-28和100-101表示执行状态的整数(以下是对应的宏定义)


2.关闭数据库sqlite3_close

✒️函数原型int sqlite3_close(sqlite3 *db);

✒️参数说明:db 关闭数据库的操作句柄

✒️返回值:同上0-28和100-101表示执行状态的整数 


3.执行SQL语句sqlite3_exec

 ✒️函数原型:

SQLITE_API int sqlite3_exec(

  sqlite3 *db,     /* The database on which the SQL executes */

  const char *zSql,            /* The SQL to be executed */

  sqlite3_callback xCallback, /*Invoke this callback routine*/

  void *pArg,               /* First argument to xCallback() */

  char **pzErrMsg           /* Write error messages here */

)

✒️参数说明:参考注释(摘自sqlite3源码)

     参数1 /* 执行SQL语句所在的数据库 */

     参数2 /* 执行的SQL语句 */

     参数3 /* 调用执行的回调函数程序 */

     参数4 /* 回调函数的第一个参数 */

     参数5 /* 记录错误信息 */

✒️返回值:同上 

4.(重要)回调函数callback 

 ✒️函数原型

static int callback(void *pArg,int nArg,char **azArg,char **azCol);

(上面是从sqlite3源码中截下来callback的函数原型,个人感觉参数名不大清晰)

static int callback(void *arg,int col_size,char **col_val,char **col_name);

✒️参数说明

        /*  参数1-void *pArg 由sqlite_exec函数传过来的参数(具体意义没有查到?)

            参数2-int nArg 回传过来的字段数(表的列数)

            参数3-char **azArg 存放表的数据的地址(字段的值)

            参数4-char **azCol 存放表的行(字段名)*/

✒️返回值

        /* 返回值为0时表中有几条数据就执行几次 */ 


五、C操作SQLite数据库

1.Demo1.c(执行select * from student.db

#include <stdio.h>
#include <sqlite3.h>

/* int callback(void *pArg, int nArg, char **azArg, char **azCol)*/
/* 回调函数,返回值为0时表中有几条数据就执行几次 */
/*  参数1-void *pArg 由sqlite_exec函数传过来的参数
    参数2-int nArg 回传过来的字段数(表的列数)
    参数3-char **azArg 存放表的数据(字段的值)
    参数4-char **azCol 存放表的行(字段名)
*/
int callback(void *pArg, int nArg, char **azArg, char **azCol){
    static int i = 0;
    if(!i){
        printf("%s\n",(char *)pArg);   //表的标题,由sqlite3_exec传过来的
        for(i=0;i<nArg;i++){
            printf("%s\t",azCol[i]);    //只打印输出一次表的字段名(表头)
        }
        printf("\n");
        printf("----------------------------------\n");
    }
    for(i=0;i<nArg;i++){
        printf("%s\t",azArg[i]);        //打印输出表的数据
    }
    printf("\n");
    return 0;
}

int main(int argc,char **argv){
    sqlite3 *pdb;
    char SQL_SELECT[] = "select * from stu_Info;";
    char *errorLog = NULL;
    void *p;
    if(argc < 2){
        printf("Usage:%s XXX.db\n",argv[0]);
        return -1;
    }else{
        if(sqlite3_open(argv[1],&pdb) == SQLITE_OK){        //打开数据库
            printf("open %s succeed!\n",argv[1]);
            if(sqlite3_exec(pdb,SQL_SELECT,callback,"student messege table",&errorLog)!=SQLITE_OK){ //执行SQL语句
                printf("SQL execute error %s\n",errorLog);    //执行失败打印错误信息
            }
        }else{
            printf("open error:%d\n",sqlite3_errcode(pdb)); //打开数据库失败输出错误码
        }
    }
    sqlite3_close(pdb);
    return 0;
}

2.Demo2.c(在demo1的基础上,将数据存在链表中)

(不会,mark以后再看看)

3.Demo3.c(创建表,并插入数据)

#include <stdio.h>
#include <sqlite3.h>

int callback(void *arg,int col_size,char **col_val,char **col_name){
    static int i = 0;
    if(!i){
        for(i=0;i<col_size;i++){
            printf("%s\t",col_name[i]);   //只打印输出一次表的字段名(表头)
        }
        printf("\n");
        printf("----------------------------------\n");
    }
    for(i=0;i<col_size;i++){
        printf("%s\t",col_val[i]);        //打印输出表的数据
    }
    printf("\n");
    return 0;
}

int main(int argc,char **argv){

    sqlite3 *pdb;
    int retn;
    char *errorLog;
    /* 创建成绩表,字段如下。为了美观代码分行,需加\连接*/
    char Create_Table[] = "create table scores( \
        ID    char primary key,\
        name  char not null,   \
        class int  not null,   \
        score int              \
    );";

    char Select_Table[] = "select * from scores;";
    char Insert_Table1[] = "insert into scores values('2022001','Socket',001,99);";
    char Insert_Table2[] = "insert into scores values('2022002','AF_INET',001,88);";
    char Insert_Table3[] = "insert into scores values('2022003','New',002,77);";
    if(argc < 2){
        printf("syntax error\nUages:%s xxx.db\n",argv[0]);
        return -1;
    }
    retn = sqlite3_open(argv[1],&pdb);
    if(retn != SQLITE_OK){
        printf("open %s error:%d\n",argv[1],sqlite3_errcode(pdb));
        return -1;
    }else{
        printf("open %s succeed\n",argv[1]);
    }

    retn = sqlite3_exec(pdb,Create_Table,NULL,NULL,&errorLog);
    if(retn != SQLITE_OK){
        printf("%s,error code:%d\n",errorLog,retn);
    }

    retn = sqlite3_exec(pdb,Insert_Table3,NULL,NULL,&errorLog);
    if(retn == SQLITE_OK){
        printf("Insert data succeed\n");
    }else{
        printf("%s,error code:%d\n",errorLog,retn);
    }

    sqlite3_exec(pdb,Select_Table,callback,NULL,&errorLog);
    sqlite3_close(pdb);
    return 0;
}
 


网站公告

今日签到

点亮在社区的每一天
去签到