天天看点

网络编程_6(数据库)十一、数据库

一二章请点击:网络编程_1(网络基础+跨主机传输)

三四章请点击:网络编程_2(网络属性+UDP(UDP模型+广播组播))

第五章请点击:网络编程_3(TCP)

第六章请点击:网络编程_4(IO模型)

七八九十章请点击:网络编程_5(超时检测+UNIX域套接字+抓包工具+包头分析)

十一、数据库

1、数据库基本概念

1.1数据(Data)

能够输入计算机并能被计算机程序识别和处理的信息集合

1.2数据库 (Database)

数据库是在数据库管理系统管理和控制之下,存放在存储介质上的数据集合

1.3常用的数据库

1)大型数据库

Oracle公司是最早开发关系数据库的厂商之一,其产品支持最广泛的操作系统平台。目前Oracle关系数据库产品的市场占有率名列前茅。

IBM 的DB2是第一个具备网上功能的多媒体关系数据库管理系统,支持包Linux在内的一系列平台。

中型数据库

Server是微软开发的数据库产品,主要支持windows平台。

2)小型数据库

mySQL是一个小型关系型数据库管理系统,开发者为瑞典MySQL AB公司,2008年被Sun公司收购,开放源码。

3)基于嵌入式的数据库

基于嵌入式Linux的数据库主要有SQLite, Firebird, Berkeley DB, eXtremeDB

Firebird是关系型数据库,功能强大,支持存储过程、SQL兼容等

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

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

eXtremeDB是内存数据库,运行效率高

1.4SQLite基础

www.sqlite.org

SQLite的源代码是C,其源代码完全开放。SQLite第一个Alpha版本诞生于2000年5月。 他是一个轻量级的嵌入式数据库。

SQLite有以下特性:

零配置一无需安装和管理配置;

储存在单一磁盘文件中的一个完整的数据库;

数据库文件可以在不同字节顺序的机器间自由共享;

支持数据库大小至2TB;

足够小,全部源码大致3万行c代码,250KB;

比目前流行的大多数数据库对数据的操作要快;

安装方式

本地安装数据库方法:

1.将“数据库Linux安装文件”中的三个安装包拷贝到虚拟机中

2.在放置三个安装包的位置,运行 sudo dpkg -i * .deb

在线安装方式:

1.确保虚拟机能联网

2.更新更新源

sudo apt-get update

3、安装软件及开发环境

apt-get install sqlite3 —>sqlite3数据库软件

apt-get install libsqlite3-dev —>sqlite3数据库开发支持库

apt-get install libsqlite3-doc —>sqlite3数据库说明文档 /usr/share/doc/sqlite3 或 /usr/share/doc/sqlite3-doc

apt-get install sqlitebrowser —>sqlite3数据库操作软件

安装成功后,终端输入以下指令,判断是否安装成功:

[email protected]:~$ sqlite3
  	出现下列语句,标识安装成功
  		SQLite version 3.7.2
  		Enter ".help" for instructions
  		Enter SQL statements terminated with a ";"
  		sqlite> 
  	
  	输入 .quit退出数据库
  		[email protected]:~$ sqlite3
  		SQLite version 3.7.2
  		Enter ".help" for instructions
  		Enter SQL statements terminated with a ";"
  	
  		sqlite> .quit
  		[email protected]:~$ 
           

2.sqlite3命令语句

SQLITE3不区分大小写;

1.sqlite创建数据库

$ sqlite3 sq.db
如果sq.db存在就是打开,如果不存在则会创建sq.db;
显示下面的内容则说明创建成功
SQLite version 3.7.2
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite>
           

2.系统命令

.命令不需要以‘;’结尾
都是以点开头,也叫做点命令
.header on 		//显示表头; .header off
.mode column 	//对齐
.timer on 		//显示时间 	.timer off
.help 	显示帮助信息,获取所有的系统命令
.quit 	退出数据库
.exit 	退出数据库
.table 	查看当前数据库下的所有表格
.databases 	显示当前打开的数据库文件
.schema  	查看表的结构
	.schema test
           

3.sql语句

注意:sql语句都是以分号结尾的;

1)创建表格

create table 表名(字段 类型,字段 类型);
create table if not exists 表名(字段 类型,字段 类型);
例子:
	sqlite> create table test(id int, name char, sex char, score float);
	sqlite> create table if not exists test(id int, name char, sex char, score float);
注意:不支持严格的类型检查,数据类型写错了,也能创建成功,不会有错误提示。
           

2)删除表格

drop table 表名;
sqlite> drop table test2;
删除表格后,表中的数据也会一并删除。
           

3)插入记录

1)全字段插入;
	insert into 表名 values (数据1,数据2,数据3,数据4);
	sqlite> insert into test values(1, "zhangsan", 'F', 90);
	sqlite> select * from test; 	//查看
	注意:
        1.数据的顺序需要与创建表格时候的字段顺序一致;
		2.字符串可以使用单引号也可使用双引号;
2)部分字段插入;
	insert into 表名(字段1, 字段2)values(数据1,数据2);
	sqlite> insert into test(name, sex) values('lisi', 'M');
	注意:
        1.数据的顺序要与前面的(字段1, 字段2)一致;
           

4)查看记录

1)查看所有记录
    select * from 表名;
	sqlite> select * from test;

2)按条件筛选:(查看某几行)
    select * from 表名 where 限制条件;
	sqlite> select * from test where score>80;
		and 	or
	sqlite> select * from test where score<90 and score>60;
	sqlite> select * from test where score>=90 or score<70;
	sqlite> select * from test where name='zhangsan' and score=90;

3)查询指定字段:(查看某几列)
    select 字段1,字段2 from 表名;
	select 字段1,字段2 from 表名 where 限制条件;
	sqlite> select name, sex from test;
	sqlite> select name, sex from test where score>60 and score<90;
           

5)更新记录

update 表名 set 字段=数值 where 字段=数值;
sqlite> UPDATE test set score=85 where name='lisi';
sqlite> UPDATE test SET id=2 where name='lisi' and score=85;
           

6)删除行

delete from 表名 where 字段=数值;
	sqlite> delete from test where id=2 and name='lisi';
删除表中所有记录;
	sqlite> delete from test;
           

7)增加列

alter table 表名 add column 字段名 类型;
sqlite> alter table test add column age int;
           

8)修改表名

alter table 老表名 rename to 新表名;
sqlite> alter table test rename to stu; 	//将test修改成stu
           

9)修改列名(字段名)

不支持直接修改列名
1.将表重新命名(a改成b)
	alter table a rename to b;
2.新建修改字段后的表(新建一个a)
	create table a (id1 int, name char, sex char, score float, age int);
3.从旧表b中取出数据,插入到新表a中;
	insert into a select * from b;
sqlite> alter table stu rename to stuinfo;
sqlite> create table stu(id1 int, name char, sex char, score float, age int);
sqlite> insert into stu select * from stuinfo;
           

10)删除列

不支持直接删除列;
1.创建一个新表b,并复制旧表a需要保留的字段信息;
	create table b as select id1, name, score from a;
2.删除旧表a
	drop table a;
3.修改新表b的名字a
	alter table b rename to a;
sqlite> create table stu1 as select id1, name, score from stu;
sqlite> drop table stu;
sqlite> alter table stu1 rename to stu;
           

11)主键(primary key)

primary key 	//主键;
create table 表名(字段名 类型 primary key, 字段名 类型);
primary key 主键:唯一标识表格中的每一条记录;
		例如id字段为主键,当表格中有id==1的记录时,不允许再插入id为1的记录了;	
注意:主键的值必须唯一,每一个表格应该都设置一个主键,而且只能设置一个;
           

12)附加指令

i)排序
select * from 表名 order by 列名 asc; 	//升序  asc可以忽略;
select * from 表名 order by 列名 desc; 	//降序
           
ii)求和
select sum(列名) as sumvalue from 表名;
           
iii)求平均值
select avg(列名) as avgvalue from 表名;
           
iv)求最大/最小值
select max(列名) as maxvalue from 表名;
select min(列名) as minvalue from 表名;
           

3.sqlite3 APIs

头文件:
	#include <sqlite3.h>   
编译时候需要加上 -lsqlite3
    gcc .c文件  -lsqlite3
           

1. sqlite3_open

功能:打开或创建数据库;
原型:
	int sqlite3_open(
    	const char *filename,   /* Database filename (UTF-8) */
  		sqlite3 **ppDb          /* OUT: SQLite db handle */
		);
参数:
    char *filename:数据库的路径+数据库名;
	sqlite3 **ppDb:sqlite句柄指针,存储打开的数据库地址;
返回值:
    成功,返回0/SQLITE_OK;
	失败,返回错误码(非0值);
例子:
    sqlite3 * db = NULL;                                             
    int ret = sqlite3_open("./sq.db", &db);
           

2. sqlite3_close

功能:关闭数据库;
原型:
	int sqlite3_close(sqlite3* db);
参数:
    sqlite3* db:指定要关闭的数据库句柄;
返回值:
    成功,返回0,SQLITE_OK;
	失败,返回错误码(非0值);
例子:
	sqlite3_close(db);
           

3. sqlite3_errmsg

功能:通过错误码获取错误信息,一般放在打开数据库失败后;
原型:
	const char *sqlite3_errmsg(sqlite3*db);
参数:
    sqlite3*db:句柄指针,存储打开失败的数据库地址;
返回值:
    返回错误码对应的错误信息;
例子:
	fprintf(stderr, "%s\n", sqlite3_errmsg(db));
           

4. sqlite3_exec

功能:执行一条sql语句;
原型:
int 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 */
);
参数:
	sqlite3* db:数据库句柄指针,要操作的数据库;
	const char *sql:sql语句;
	int (*callback)(void*,int,char**,char**):回调函数,可以指向 int func(void*, int, char**, char**);
		注意:只有在查询sql语句时候使用;
    void *arg:传入给回调函数的参数;
	char **errmsg:错误信息;
返回值:
    成功,返回0;SQLITE_OK;
    失败,返回错误码,非0参数;	    
           

回调函数

回调函数:只有在查询的时候使用;
    int callback(void* arg,int f_num, char** f_value,char** f_name);
功能:每找到一条记录就会自动执行一次该函数;
参数:
    void* arg:传递给回调函数的参数;
	int f_num:查询结果的列数(字段数);
	char** f_value:该指针指向存储查询结果的指针数组;
		例子: id name score;
			f_value[0] = "1" 			//id
             f_value[1] = "zhangsan"      //name
             f_value[2] = "90.0" ;		 //score;
           for(i=0; i<f_num; i++)
           {
           		printf("%s ",f_value[i]);
           } 
    char** f_name:该指针指向存储字段名的指针数组;
         例子: id name score;
			f_name[0] = "id";
			f_name[1] = "name";
			f_name[2] = "score";
           
#include <sqlite3.h>
#include <stdio.h>
#include <string.h>
int callback(void* arg, int f_num, char** f_value, char** f_name);
int main(int argc, const char *argv[])
{
    //创建并打开数据库
    sqlite3 * db = NULL;
    int ret = sqlite3_open("./sq.db", &db);
    if(ret != 0)
    {
        fprintf(stderr, "数据库打开失败\n");
        //打印错误信息
        fprintf(stderr, "%s\n", sqlite3_errmsg(db));
        return -1;
    }
    printf("数据库打开成功\n");
    char sql[256] = "";
    char *errmsg = NULL;
    //创建表
    bzero(sql, sizeof(sql));
//  sprintf(sql, "create table if not exists stu(id int primary key, name char, score float )");
    sprintf(sql, "create table if not exists stu(id int, name char, score float )");
    if(sqlite3_exec(db, sql, NULL, NULL, &errmsg)!=0)
    {
        fprintf(stderr, "sqlite3_exec:%s\n", errmsg);
        goto END;
    }
    printf("创建表格成功\n");
    //插入数据
    int i = 0;
    for(i=1; i<4; i++)
    {
        bzero(sql, sizeof(sql));
        sprintf(sql, "insert into stu values(%d, \"zs\", 90)", i);

        if(sqlite3_exec(db, sql, NULL, NULL, &errmsg)!=0)
        {
            fprintf(stderr, "sqlite3_exec:%s\n", errmsg);
            goto END;
        }
    }
    printf("插入数据成功\n");
    //查询数据
    bzero(sql, sizeof(sql));
    sprintf(sql, "select * from stu");
    int flag = 1;
    if(sqlite3_exec(db, sql, callback, &flag, &errmsg) !=0)
    {
        fprintf(stderr, "sqlite3_exec:%s\n", errmsg);
        goto END;
    }
    printf("查询数据成功\n");
END:
    //关闭数据库
    if(sqlite3_close(db) != 0)
    {
        fprintf(stderr, "数据库关闭失败\n");
        return -1;
    }
    return 0;
}
//回调函数
int callback(void* arg, int f_num, char** f_value, char** f_name)
{                                                                                                     
    int i = 0;
    if(1 == *(int*)arg)     //防止表头重复打印
    {
        for(i=0 ;i<f_num; i++)
        {
            printf("%-10s", f_name[i]);     //打印字段名
        }
        putchar(10);
        *(int*)arg = 0;     //通过指针的方式间接访问 修改flag
    }
    for(i=0; i<f_num; i++)
    {
        printf("%-10s", f_value[i]);    //打印查到的数据
    }
    putchar(10);
    return 0;
}
           

5. 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 */
    		);
参数:
    sqlite3 *db:句柄指针,存储打开的数据库
    const char *zSql:sql语句,**只能填写查询相关的sql语句**;
    char *** pResult:用来指向sql执行结果的指针,包括表头的数据,需要手动释放。
    					由函数将查询到的结果放到指针数组
    					指针数组保存结果字符串首地址,包括表头;
	int *pnRow:满足条件的记录条数(行数);
    int *pnColumn:满足条件的字段数(列数);
	char **pzErrmsg:错误信息;
返回值:
    成功,返回0,SQLITE_OK;
	失败,返回错误码,非0参数;	   
释放空间:
	void sqlite3_free_table(char **result);