Linux网络编程【11】(Sqlite数据库)

339 阅读7分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

数据库

官网:

www.sqlite.org

1 在ubuntu中安装sqlite数据库

离线安装:

将.deb包拖入ubuntu中,并执行sudo dpkg -i *.deb即可

在线安装:

sudo apt-get install sqlite3 libsqlite3-dev

安装完之后进行测试:

终端输入sqlite3,如果能够进入数据库说明安装成功

图片.png

2 创建或者打开指定数据库

方法1:在终端数据sqlite3的后面加数据库的名字,数据库名一般以.db作为后缀名

图片.png

方法2:终端输入sqlite3,然后进入软件之后在输入.open 跟数据库名

图片.png

3 数据库的操作

3.1 数据库的命令分类

系统命令:是以.开头的命令,主要用于对当前数据库操作

注意:系统命令后面不能加;

普通命令:是以;结尾的命令,主要对数据库中的表进行操作

注意:普通命令前面不能加.

3.2 常用的系统命令

.help 查看帮助信息,列出所有的系统命令 .exit 退出数据库 .quit 退出数据库 .databases 查看当前数据库的信息 .tables 列出当前数据库中所有表的表名 .schema 列出当前数据库中所有表的结构

3.3数据库的结构

数据库类似excl表格,当创建好一个数据库之后,不会自动给你创建表的,需要自己创建

数据库中表的结构:

图片.png

3.4 数据库中常用sql语句

【1】sqlite常用命令

1-- 安装数据库:

sudo dpkg -i *.deb

2-- 创建数据库

sqlite3 stu.db

3-- 系统命令
  • 系统命令 以 "."开头(系统命令后面不能加;)
  • 普通命令 ,以";"结束 (普通命令前面不能加.)
.schema  查看表的结构
.quit    退出数据库
.exit    退出数据库
.help    查看帮助信息
.databases 查看数据库
.tables  显示数据库中所有的表的表名
4-- 普通命令
1-- 创建一张表

​ create table 表名(字段名称1 字段类型,字段名称2 字段类型, ....);

例如:create table stu(id int, name char, sex char , score int);

2-- 向表中插入一条记录

​ insert into 表名 values (字段值1,字段值2,...);

insert into stu values(1001, 'zhangsan', 'm', 89);

insert into stu (id, name, sex,score) values(1002, 'lisi', 'm', 99);

3-- 查询记录
select * from stu;                                    // 查找所有的记录
select * from stu where id=1001;                      // 查找符号条件的记录
select * from stu where id=1001 and name='zhangsan';  // 字符串需要加引号
select * from stu where name='zhangsan' or score=92; 
  • ==.headers on 显示列表名==
  • ==.mode column 按照列显示内容==
4-- 删除记录

delete from stu where id=1004;

5-- 更新记录

update stu set score=98 where id=1003;

6-- 删除一张表

drop table stu;

7-- 添加一列

alter table stu add column score int;

8-- 删除一列

sqlite3 不允许直接删除一列

  • ​ 1)先创建一张新表 ​ create table stu1 as select id , name from stu;
  • 2)删除原来的旧表 drop table stu;
  • 3)对新表重命名 alter table stu1 rename to stu;
9-- 数据库主键(既设置的数据将会是唯一存在的)

create table usr(name text primary key , passwd text);

比如说注册用户的时候,可以把用户名设置成主键,这样用对应某一个用户名的密码等信息就成了唯一的。

4 sqlite数据库常用api

(1)int sqlite3_open

编程时要注意用这个打开,没有这个会很离谱的。

int sqlite3_open(
         const char *filename,   /* Database filename (UTF-8) */
         sqlite3 **ppDb          /* OUT: SQLite db handle */
         );
    功能:打开或者创建一个数据库
    参数:
        filename   数据库名字
        ppdb      操作数据库的指针,句柄。
    返回值:
        成功 SQLITE_OK
        失败 error_code,可以通过sqlite3_errmsg获取错误信息

(2)const char *sqlite3_errmsg

2const char *sqlite3_errmsg(sqlite3* db);
    功能:获取错误信息描述

(3)int sqlite3_close

3int sqlite3_close(sqlite3* db);
    功能:关闭一个数据库

(4)int sqlite3_exec

4int sqlite3_exec(
         sqlite3* db,                                  /* 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语句
    参数:
        db  数据库的句柄指针
        sql  将要被执行sql语句
        callback 回调函数, 只有在查询语句时,才给回调函数传参
        arg  为callback 传参的
        errmsg 错误信息的地址
    返回值:
        成功 SQLITE_OK
        出错 errcode 错误码,通过参数errmsg可以输出

***********************************************************

    int (*callback)(void* arg ,int  ncolumn ,char** f_value,char** f_name)
    功能:得到查询结果
    参数:
        arg  为回调函数传递参数使用的
        ncolumn  记录中包含的字段的数目(列数)
        f_value  包含每个字段值的指针数组
        f_name   包含每个字段名称的指针数组
    返回值:
        成功 0
        出错 非0
*********************************************************

(5)int sqlite3_get_table

5int sqlite3_get_table(
     sqlite3 *db,          /* An open database */
     const char *zSql,     /* SQL to be evaluated */
     char ***pazResult,    /* Results of the query */
     int *pnRow,           /* Number of result rows written here */
     int *pnColumn,        /* Number of result columns written here */
     char **pzErrmsg       /* Error msg written here */
     );
    功能:查询数据库,它会创建一个新的内存区域来存放查询的结果信息
    参数:db       数据库操作句柄
          sql      数据库的sql语句
          azResult 查询的结果
          nRow     行数
          nColumn  列数
          errmsg   错误消息
	返回值:
	     成功 0
         出错 errcode
	nrow的值为查询到的符合条件的记录数(不包括字段名)。
	ncolumn的值为查询到的符合条件的字段数。

(6)void sqlite3_free_table

6void sqlite3_free_table(char **result);
	功能:释放内存

代码:

#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h>  //sqlite3数据库使用函数时需要包含的头文件

//sqlite3的库是第三方提供的动态库,所以编译时需要手动链接库文件 -lsqlite3

#define DBFILE "stu.db"
#define TABLE "dc21071"

int flags = 0;

void do_insert(sqlite3 *db);
int callback(void *arg, int ncolumn,char **text, char **name);
void do_select(sqlite3 *db);
int main(int argc, char const *argv[])
{
    sqlite3 *db;

    //创建或者打开一个数据库
    if(sqlite3_open(DBFILE, &db) != SQLITE_OK)
    {
        printf("错误:%s\n", sqlite3_errmsg(db));
        exit(1);
    }
    else 
    {
        printf("成功:数据库已经打开或者创建成功了\n");
    }

    //创建一张表
    char sql[128] = {0};
    char *errmsg;
    sprintf(sql, "create table %s(id int, name char, sex char, score int)", TABLE);
    if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
    {
        printf("错误:%s\n", errmsg);
    }
    else 
    {
        printf("成功:表创建成功\n");
    }

    char num;
    while(1)
    {
        printf("----------------------------------------------------------\n");
        printf("--- 1.插入数据 2.查询数据 3.修改数据 4.删除数据 5.退出 ---\n");
        printf("----------------------------------------------------------\n");
        printf(">>> ");

        scanf("%c", &num);
        getchar();

        switch(num)
        {
        case '1':
            do_insert(db);
            break;
        case '2':
            flags = 0;
            do_select(db);
            break;
        case '3':
            break;
        case '4':
            break;
        case '5':
            //关闭数据库
            sqlite3_close(db);
            exit(0);
            break;
        default:
            printf("您输入的有误,请重新输入\n");
            break;
        }
    }

    return 0;
}

void do_insert(sqlite3 *db)
{
    int id;
    char name[32];
    char sex;
    int score;

    printf("请输入学号:");
    scanf("%d", &id);
    printf("请输入姓名:");
    scanf("%s", name);
    getchar();
    printf("请输入性别:");
    scanf("%c", &sex);
    printf("请输入分数:");
    scanf("%d", &score);
    getchar();

    char sql[128] = {0};
    char *errmsg;
    sprintf(sql, "insert into %s values(%d, '%s', '%c', %d)", TABLE, id, name, sex, score);
    if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
    {
        printf("错误:%s\n", errmsg);
    }
    else 
    {
        printf("成功:数据插入成功\n");
    }
}

int callback(void *arg, int ncolumn, char **text, char **name)
{
    // printf("ncolumn = %d\n", ncolumn);
    // printf("text[0] = %s, text[1] = %s\n", text[0], text[1]);
    // printf("name[0] = %s, name[1] = %s\n", name[0], name[1]);

    int i;

    if(flags == 0)
    {
        for(i = 0; i < ncolumn; i++)
        {
            printf("%-11s", name[i]);
        }
        putchar(10);
        puts("---------------------------------------");
    
        flags = 1;
    }
    for(i = 0; i < ncolumn; i++)
    {
        printf("%-11s", text[i]);
    }
    putchar(10);

    return 0;
}

void do_select(sqlite3 *db)
{
    char sql[128] = {0};
    char *errmsg;

    sprintf(sql, "select * from %s", TABLE);

    //sqlite3_exec函数的回调函数在查询的时候会自动根据记录的条数调用很多次
    //回调函数每调用一次只获取一行记录的内容
    if(sqlite3_exec(db, sql, callback, NULL, &errmsg) != SQLITE_OK)
    {
        printf("错误:%s\n", errmsg);
    }
    else 
    {
        printf("成功:数据查询成功\n");
    }
}

(7)sqlite3_get_table

int sqlite3_get_table(
  sqlite3 *db,          /* An open database */
  const char *zSql,     /* SQL to be evaluated */
  char ***pazResult,    /* Results of the query */
  int *pnRow,           /* Number of result rows written here */
  int *pnColumn,        /* Number of result columns written here */
  char **pzErrmsg       /* Error msg written here */
);
void sqlite3_free_table(char **result);
以结果表格式为例,假设查询结果如下:

    姓名 | 年龄
    -----------------------
    爱丽丝 | 43
    鲍勃 | 28
    辛迪 | 21

有两列(M==2)和三行(N==3)。因此,结果表有 8 个条目。假设结果表存储在名为 azResult 的数组中。然后 azResult 保存了这个内容:

    azResult[0] = "姓名"; 
    azResult[1] = "年龄"; 
    azResult[2] = "爱丽丝"; 
    azResult[3] = "43"; 
    azResult[4] = "鲍勃"; 
    azResult[5] = "28"; 
    azResult[6] = "辛迪"; 
    azResult[7] = "21";

📣注意通过char ***pazResult来判定是否查询成功,==没有查到返回0==;

void do_get_table(sqlite3 *db)
{
    char sql[128] = {0};
    char **ret;
    int nrow, ncolumn;
    char *errmsg;

    sprintf(sql, "select * from %s where id = 1001 and name = 'lisi'", TABLE);

    //sqlite3_get_table函数可以查询一条记录是否存在,
    //如果存在,第四个参数一定大于0,如果不存在则等于0
    if(sqlite3_get_table(db, sql, &ret, &nrow, &ncolumn, &errmsg) != SQLITE_OK)
    {
        printf("错误:%s\n", errmsg);
    }

    printf("行数:%d, 列数:%d\n", nrow, ncolumn);
    // printf("ret[0] = %s, ret[1] = %s\n", ret[0], ret[1]);
    // printf("ret[4] = %s, ret[5] = %s\n", ret[4], ret[5]);

    int i, j, n = 0;
    for(i = 0; i < nrow + 1; i++)
    {
        for(j = 0; j < ncolumn; j++)
        {
            printf("%-11s", ret[n++]);
        }
        putchar(10);
    }
}