天天看點

網絡程式設計_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);