版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
第21章Linux系統(tǒng)常用數(shù)據(jù)庫及接口在大型的企業(yè)應用領(lǐng)域,數(shù)據(jù)庫是作為一個單獨的系統(tǒng)存在,各種專業(yè)數(shù)據(jù)庫都提供了豐富的管理功能和網(wǎng)絡(luò)服務(wù)功能。對于程序設(shè)計來說,所進行的工作更趨向于從數(shù)據(jù)處理中抽象出來的業(yè)務(wù)邏輯,于是產(chǎn)生了數(shù)據(jù)層、邏輯層、表示層三層模型概念。數(shù)據(jù)層通常是由數(shù)據(jù)庫管理,它可以是存放在本地計算機中的一個數(shù)據(jù)文件,也可以是來自網(wǎng)絡(luò)中多臺計算機組成的數(shù)據(jù)庫服務(wù)器集群。邏輯層是有關(guān)數(shù)據(jù)對象處理的應用程序?qū)崿F(xiàn),它通過接口訪問數(shù)據(jù)庫,再將處理后的數(shù)據(jù)傳送給表示層,或者將表示層中獲得的數(shù)據(jù)進行處理后存儲到數(shù)據(jù)庫中。表示層可以是用程序語言開發(fā)的界面,甚至可以是瀏覽器中的網(wǎng)頁或者是一條手機短信息。三層模型對大型企業(yè)應用設(shè)計所面臨的問題進行了細分,Linux系統(tǒng)中C語言程序設(shè)計所面向的問題主要為其中的應用層。本章將通過介紹Linux系統(tǒng)常用數(shù)據(jù)庫及接口來進一步說明其概念。21.1SQLite數(shù)據(jù)庫SQLite數(shù)據(jù)庫是一種開源的嵌入式數(shù)據(jù)庫系統(tǒng),與BerkeleyDB數(shù)據(jù)包相比,SQLite雖然在性能上不及,但使用起來更為簡單方便。因此SQLite數(shù)據(jù)庫是設(shè)計小型應用系統(tǒng)的首選,配合一些開源工具使用也可使其成為具有網(wǎng)絡(luò)訪問功能的數(shù)據(jù)庫。21.1.1SQLite簡介SQLite是理查德·希普用C語言編寫的開源嵌入式數(shù)據(jù)庫引擎。其數(shù)據(jù)庫管理功能完全獨立,不具有外部依賴性。與BerkeleyDB數(shù)據(jù)包相比,SQLite支持多數(shù)SQL92標準,可用SQL語句對數(shù)據(jù)庫進行管理。SQLite與Linux系統(tǒng)的結(jié)合也非常好,其原始的目標平臺即Linux系統(tǒng),并且支持多種硬件架構(gòu)。此外,SQLite非常健壯,能支持TB級別數(shù)據(jù)操作,并且為大多數(shù)程序設(shè)計語言提供了接口函數(shù)庫,特別是C語言。SQLite通過數(shù)據(jù)庫級共享鎖和實現(xiàn)事務(wù)處理,并支持原子操作。當多個進程同時向同一數(shù)據(jù)庫寫入文件時,只有一個進程能率先搶占到數(shù)據(jù)庫資源。進程可以用共享鎖將數(shù)據(jù)庫鎖定,這樣其它進程就無法進行讀寫操作,保證數(shù)據(jù)的完整性。21.1.1SQLite簡介在內(nèi)部,SQLite由以下幾個組件組成:SQL編譯器、內(nèi)核、后端以及附件,如圖所示。SQLite通過利用虛擬機和虛擬數(shù)據(jù)庫引擎(VDBE),使調(diào)試、修改和擴展SQLite的內(nèi)核變得更加方便。所有SQL語句都被編譯成易讀的、可以在SQLite虛擬機中執(zhí)行的程序集。21.1.1SQLite簡介SQLite數(shù)據(jù)庫最大容量為2TB,每個數(shù)據(jù)庫都保存在一個二進制文件中。SQLite的數(shù)據(jù)庫文件與操作系統(tǒng)內(nèi)碼無關(guān),因此可以在不同操作系統(tǒng)間共用。SQLite根據(jù)該文件的權(quán)限信息獲得其數(shù)據(jù)庫權(quán)限。SQLite不支持靜態(tài)數(shù)據(jù)類型,而是使用列關(guān)系。這意味著它的數(shù)據(jù)類型不具有表列屬性,而具有數(shù)據(jù)本身的屬性。當某個值插入數(shù)據(jù)庫時,SQLite將檢查它的類型。如果該類型與關(guān)聯(lián)的列不匹配,則SQLite會嘗試將該值轉(zhuǎn)換成列類型。如果不能轉(zhuǎn)換,則該值將作為其本身具有的類型存儲。SQLite支持NULL、INTEGER、REAL、TEXT和BLOB數(shù)據(jù)類型。安裝SQLite可登錄其官方站點獲得源代碼,地址為,或輸入下列命令:apt-getinstallsqlitelibsqlite3-dev21.1.1SQLite簡介SQLite項目中有一個命令行數(shù)據(jù)庫管理器和數(shù)據(jù)庫分析器,可在其官方站點獲得。這些工具都是以文本命令模式運行在終端中的,使用起來并不方便。支持SQLite數(shù)據(jù)庫的圖形化管理工具有很多,例如可通過FireFox瀏覽器登錄“US/firefox/addon/5817”,安裝一款名為SQLiteManager插件,該插件可以在瀏覽器中管理SQLite數(shù)據(jù)庫文件。21.1.1SQLite簡介SQLite也有一些缺陷,它沒有用戶賬戶概念,只能借助Linux系統(tǒng)中的用戶權(quán)限機制實施對數(shù)據(jù)庫訪問權(quán)限的保護。這種模式下,針對每個用戶的存儲配額管理十分困難。SQLite支持多數(shù)(但不是全部)的SQL92標準。不受支持的一些功能包括完全觸發(fā)器支持和可寫視圖。SQLite只提供數(shù)據(jù)庫級的鎖定,雖然有一些增加并發(fā)的技巧,但是,如果應用程序需要針對數(shù)據(jù)表或表記錄的鎖定,那么它不能夠滿足需求。由于資源占用少、性能良好和零管理成本,SQLite數(shù)據(jù)庫有了用途廣泛,它將為那些以前無法提供用作持久數(shù)據(jù)的后端的數(shù)據(jù)庫的應用程序提供了高效的性能。因此,在Linux系統(tǒng)應用程序開發(fā)中,不再需要使用文本文件實現(xiàn)持久存儲。SQLite之類的嵌入式數(shù)據(jù)庫的易用性可以加快應用程序的開發(fā),并使得小型應用程序能夠完全支持復雜的SQL。這一點對于移動設(shè)備上的應用程序來說尤其重要。21.1.2連接SQLite數(shù)據(jù)庫SQLite數(shù)據(jù)庫的接口函數(shù)包含在頭文件sqlite3.h中,連接數(shù)據(jù)庫只需要sqlite3_open()一條函數(shù)即可。它的一般形式是:intsqlite3_open(
constchar*filename,
//UTF8編碼的數(shù)據(jù)庫文件名
sqlite3**ppDb);
//SQLite數(shù)據(jù)庫標識符指針該函數(shù)有兩條參數(shù),filename用于指定數(shù)據(jù)庫路徑和文件名,它必須是以UTF8編碼的字符串。如果字符串以UTF16編碼,那么可以使用sqlite3_open16()函數(shù)代替。sqlite3_open16()函數(shù)的參數(shù)與sqlite3_open()函數(shù)相同。**ppDb參數(shù)用于返回一個數(shù)據(jù)庫操作符的指針,打開數(shù)據(jù)庫成功后就可以用該指針進行數(shù)據(jù)庫操作。如果打開數(shù)據(jù)庫成功,函數(shù)的返回值為0,否則返回一個錯誤代碼。21.1.2連接SQLite數(shù)據(jù)庫sqlite3_open_v2()函數(shù)可用于打開和創(chuàng)建數(shù)據(jù)庫文件,它比sqlite3_open()函數(shù)多出兩條參數(shù),使用起來也更為靈活。sqlite3_open_v2()函數(shù)的一般形式為:intsqlite3_open_v2(
constchar*filename,
//UTF8編碼的數(shù)據(jù)庫文件名
sqlite3**ppDb,
//SQLite數(shù)據(jù)庫標識符指針
intflags,
//標志
constchar*zVfs);
//VFS對象的名稱filename參數(shù)為數(shù)據(jù)庫文件名,如果文件名為“:memory:”,該函數(shù)會在內(nèi)存中創(chuàng)建一個私有的臨時文件;如果文件名為空,那么將在本地創(chuàng)建一個臨時文件,當數(shù)據(jù)庫標識符被關(guān)閉時臨時文件會自動刪除。flag參數(shù)用于設(shè)定打開方式,它的取值范圍如后表所示。21.1.2連接SQLite數(shù)據(jù)庫參
數(shù)
名說
明SQLITE_OPEN_NOMUTEX如果該標志被設(shè)置,并且在編譯或運行時沒有將程序設(shè)定為單線程模式,數(shù)據(jù)庫連接將以多線程方式工作SQLITE_OPEN_FULLMUTEX如果該標志被設(shè)置,無論在編譯或運行時有沒有將程序設(shè)定為單線程模式,數(shù)據(jù)庫連接都會以多線程方式工作SQLITE_OPEN_READONLY以只讀方式打開數(shù)據(jù)庫文件,如果數(shù)據(jù)庫文件不存在會造成錯誤SQLITE_OPEN_READWRITE以讀寫方式打開數(shù)據(jù)庫文件,但如果用戶沒有文件寫權(quán)限,那么將以只讀方式操作數(shù)據(jù)庫SQLITE_OPEN_CREATE如果數(shù)據(jù)庫文件不存在則創(chuàng)建一個新數(shù)據(jù)庫文件,在sqlite3_open()函數(shù)和sqlite3_open16()函數(shù)中為默認行為21.1.2連接SQLite數(shù)據(jù)庫SQLITE_OPEN_NOMUTEX標志與SQLITE_OPEN_FULLMUTEX標志不能同時使用。SQLITE_OPEN_CREATE標志必須與SQLITE_OPEN_READWRITE標志同時使用。同時使用多個標志時用按位或“|”運算符連接。zVfs參數(shù)是sqlite3_vfs結(jié)構(gòu)的名稱,該結(jié)構(gòu)是為操作系統(tǒng)接口定義的對象,如果以NULL作為實際參數(shù),那么系統(tǒng)將使用默認sqlite3_vfs對象。sqlite3_vfs結(jié)構(gòu)的定義如下:typedefstructsqlite3_vfssqlite3_vfs;structsqlite3_vfs{
intiVersion;
//結(jié)構(gòu)的版本號
intszOsFile; //sqlite3_file子集的長度
intmxPathname;
//文件路徑最大長度
sqlite3_vfs*pNext;
//下一個注冊的VFS
constchar*zName;
//虛擬文件系統(tǒng)的名稱
void*pAppData;
//指向應用程序特征的數(shù)據(jù)
int(*xOpen)(sqlite3_vfs*,constchar*zName,sqlite3_file*,
intflags,int*pOutFlags);
int(*xDelete)(sqlite3_vfs*,constchar*zName,intsyncDir);
int(*xAccess)(sqlite3_vfs*,constchar*zName,intflags,int*pResOut);
int(*xFullPathname)(sqlite3_vfs*,constchar*zName,intnOut,char*zOut);
void*(*xDlOpen)(sqlite3_vfs*,constchar*zFilename);
void(*xDlError)(sqlite3_vfs*,intnByte,char*zErrMsg);
void(*(*xDlSym)(sqlite3_vfs*,void*,constchar*zSymbol))(void);
void(*xDlClose)(sqlite3_vfs*,void*);
int(*xRandomness)(sqlite3_vfs*,intnByte,char
*zOut);
int(*xSleep)(sqlite3_vfs*,intmicroseconds);
int(*xCurrentTime)(sqlite3_vfs*,double*);
int(*xGetLastError)(sqlite3_vfs*,int,char*);};21.1.2連接SQLite數(shù)據(jù)庫sqlite3_vfs對象的接口定義在SQLite核心和操作系統(tǒng)之間。vfs的意義為虛擬文件系統(tǒng)。iVersion成員代表對象的版本號,默認值為1。如果在將來的SQLite版本中iVersion的值增大,說明sqlite3_vfs對象已改進,其中的成員會有變化。szOsFil成員用于定義sqlite3_file子集的結(jié)構(gòu)長度,mxPathname成員用于限定VFS中的路徑名最大長度。pNext指針用于指向另一個sqlite3_vfs,多個已注冊的sqlite3_vfs對象可通過pNext指針組成鏈表。因此可以將多個文件作為同一個數(shù)據(jù)庫文件,通過sqlite3_vfs對象來管理。sqlite3_errcode()函數(shù)通常用來獲取最近調(diào)用的數(shù)據(jù)庫接口返回的錯誤代碼。sqlite3_errmsg()函數(shù)則用來得到這些錯誤代碼所對應的文字說明,這些錯誤信息將以UTF-8的編碼返回,并且在下一次調(diào)用任何SQLite接口函數(shù)的時候被清除。如果要以UTF-16編碼返回錯誤文字信息,可使用sqlite3_errmsg16()函數(shù)它們的一般形式是:intsqlite3_errcode(sqlite3*db);constchar*sqlite3_errmsg(sqlite3*);constvoid*sqlite3_errmsg16(sqlite3*);可用的錯誤代碼如后表所示。21.1.2連接SQLite數(shù)據(jù)庫代
碼十進制值說
明SQLITE_OK0操作成功SQLITE_ERROR1SQL錯誤或找不到數(shù)據(jù)庫SQLITE_INTERNAL2SQLite中的內(nèi)部邏輯錯誤SQLITE_PERM3拒絕訪問錯誤SQLITE_ABORT4回調(diào)程序請求被終止SQLITE_BUSY5數(shù)據(jù)庫被鎖定SQLITE_LOCKED6數(shù)據(jù)表被鎖定SQLITE_NOMEM7動態(tài)內(nèi)存分配失敗SQLITE_READONLY8對只讀數(shù)據(jù)庫進行寫入操作失敗SQLITE_INTERRUPT9通過調(diào)用sqlite3_interrupt()函數(shù)停止了操作SQLITE_IOERR10磁盤I/O錯誤發(fā)生SQLITE_CORRUPT11數(shù)據(jù)庫磁盤映像是畸形的SQLITE_NOTFOUND12表或記錄未找到SQLITE_FULL13數(shù)據(jù)庫已滿,插入數(shù)據(jù)失敗SQLITE_CANTOPEN14不能打開數(shù)據(jù)庫文件SQLITE_PROTOCOL15數(shù)據(jù)庫鎖定協(xié)議錯誤SQLITE_EMPTY16數(shù)據(jù)庫是空的SQLITE_SCHEMA17數(shù)據(jù)庫計劃被改變SQLITE_TOOBIG18字符串或BLOB類型操作了最大可用長度SQLITE_CONSTRAINT19由于強制原因而終止SQLITE_MISMATCH20數(shù)據(jù)類型不匹配SQLITE_MISUSE21函數(shù)庫使用不正確SQLITE_NOLFS22使用操作系統(tǒng)細節(jié)在本機上不支持SQLITE_AUTH23拒絕授權(quán)SQLITE_FORMAT24輔助數(shù)據(jù)庫格式錯誤SQLITE_RANGE25sqlite3_bind()函數(shù)的第二個參數(shù)超出界限SQLITE_NOTADB26打開的文件不是一個數(shù)據(jù)庫文件SQLITE_ROW100sqlite3_step()函數(shù)已進入到另一行SQLITE_DONE101sqlite3_step()函數(shù)已經(jīng)結(jié)束執(zhí)行21.1.2連接SQLite數(shù)據(jù)庫當數(shù)據(jù)庫文件不需要再被使用時,可以使用sqlite3_close()函數(shù)將其關(guān)閉,如果再次對已關(guān)閉的數(shù)據(jù)庫操作符進行操作將造成錯誤。它的一般形式如下:intsqlite3_close(sqlite3*);下面將以一個簡單的例子演示數(shù)據(jù)庫的連接操作,這個例子也可以被定義為頭文件放在程序中,在程序的開始調(diào)用。(21_1_2.c)程序中將數(shù)據(jù)庫標識符定義為全局變量,這樣各個函數(shù)都可以使用該標識符,簡化了函數(shù)設(shè)計的難度,但對函數(shù)的通用性產(chǎn)生了不良影響。程序定義了兩個函數(shù),分別用于打開和關(guān)閉數(shù)據(jù)庫,并將操作后的錯誤代碼作為返回值調(diào)用給函數(shù)。實際應用中,數(shù)據(jù)庫連接部分通常被定義為一個頭文件,即本例中省略主函數(shù)的部分。這樣一來程序中的各個部分都可以進行數(shù)據(jù)庫操作,而且可以實現(xiàn)同一個程序中不同數(shù)據(jù)庫接口的操作。21.1.3SQLite命令執(zhí)行函數(shù)SQLite的SQL命令執(zhí)行函數(shù)只有sqlite3_exec()一條,但是它也能很好地滿足工作需要。它的一般形式為:intsqlite3_exec(
sqlite3*,
//有效的數(shù)據(jù)庫標識符
constchar*sql,
//SQL命令字符串
int(*callback)(void*,int,char**,char**),
//回調(diào)函數(shù)
void*,
//第一個回調(diào)參數(shù)
char**errmsg
//將錯誤信息寫到此指針指向的地址);函數(shù)的第三個參數(shù)是回調(diào)函數(shù)的指針,回調(diào)函數(shù)是按一定規(guī)則定義的事務(wù)處理函數(shù),當sqlite3_exec()函數(shù)執(zhí)行成功時將調(diào)用回調(diào)函數(shù),sqlite3_exec()函數(shù)的第四個參數(shù)被作為回調(diào)函數(shù)的第一個參數(shù)傳送過去。errmsg參數(shù)用于將錯誤信息寫入到指定的內(nèi)存空間中,該信息是一個字符串。如果只是執(zhí)行簡單的SQL命令,那么第三個參數(shù)與第四個參數(shù)可以為NULL。(21_1_3)21.1.4SQLite檢索查詢結(jié)果函數(shù)SQLite數(shù)據(jù)庫可通過SQL語句執(zhí)行函數(shù)執(zhí)行SQL查詢語句檢索相關(guān)數(shù)據(jù),并將數(shù)據(jù)以字符串形式返回給程序。sqlite3_get_table()函數(shù)用于檢索數(shù)據(jù)表內(nèi)的數(shù)據(jù),它的一般形式是:intsqlite3_get_table(
sqlite3*db,
//可用的數(shù)據(jù)庫標識符
constchar*zSql,
//SQL查詢語句
char***pazResult,
//查詢結(jié)果
int*pnRow,
//所查詢到結(jié)果的行數(shù)
int*pnColumn,
//所查詢到結(jié)果的列數(shù)
char**pzErrmsg
//錯誤信息寫入的地址);21.1.4SQLite檢索查詢結(jié)果函數(shù)函數(shù)的第二個參數(shù)是一條SQL查詢語句,通常該語句是SELECT語句。如果執(zhí)行查詢語句成功,那么所有的查詢結(jié)果將以字符串的形式返回給***pazResult參數(shù)所指向的內(nèi)存空間,***pazResult可以視作一個指向二維字符數(shù)組的指針。參數(shù)pnRow和pnColumn分別用來保存查詢結(jié)果中的行數(shù)和列數(shù),即使查詢到的結(jié)果為0條數(shù)據(jù),返回給***pazResult的也有一條,這一條是字段名信息。假設(shè)數(shù)據(jù)庫中存在call_list數(shù)據(jù)表,該表中有一條數(shù)據(jù),那么使用“SELECT*
FROMcall_list”語句進行查詢返回的結(jié)果為:id
type
telnum
bttime
tcount
charge_rate
charge_sum1
0
12345
20090331120011
30
0.36
0.36//pnRow的值為2,pnColumn的值為721.1.4SQLite檢索查詢結(jié)果函數(shù)如果查詢操作產(chǎn)生了錯誤,錯誤文本信息將被寫入**pzErrmsg參數(shù)所指向的內(nèi)存地址中。當sqlite3_get_table()函數(shù)執(zhí)行成功時返回1,否則返回一個錯誤代碼。執(zhí)行完檢索查詢結(jié)果函數(shù)后,需要使用sqlite3_free_table()函數(shù)將***pazResult參數(shù)所使用的內(nèi)存空間釋放,否則會造成內(nèi)存溢出。它的一般形式是:voidsqlite3_free_table(char**result);下面將以一個例子說明檢索查詢結(jié)果函數(shù)的操作方法。(21_1_4.c)本例中使用sqlite3_get_table()函數(shù)將數(shù)據(jù)表中的結(jié)果輸出到一個動態(tài)的內(nèi)存空間中,這種方法簡單易懂,但并不是SQLite數(shù)據(jù)庫檢索查詢結(jié)果操作的唯一方法。sqlite3_exec()函數(shù)也可以進行查詢操作,并且將查詢結(jié)果返回給回調(diào)函數(shù)處理。另外SQLite也支持與PostgreSQL數(shù)據(jù)庫相似的游標操作,具體用法請參考SQLite源碼包中的文檔。21.2MySQL數(shù)據(jù)庫MySQL是一個開放源碼的小型關(guān)系數(shù)據(jù)庫管理系統(tǒng),開發(fā)者為瑞典MySQLAB公司。2008年,美國Sun公司正式收購MySQL,但MySQL依然使用GPL許可證發(fā)行。目前MySQL被廣泛地應用在Linux系統(tǒng)上。由于其體積小、速度快、總體擁有成本低,尤其是開放源碼這一特點,許多中小型企業(yè)為了降低數(shù)據(jù)庫總體擁有成本而選擇了MySQL作為企業(yè)應用數(shù)據(jù)庫。MySQL的特性有:使用C和C++編寫,并使用了多種編譯器進行測試,保證源代碼的可移植性。支持Linux、MacOS、OpenBSD、Windows等多種操作系統(tǒng)。為多種編程語言提供了API。這些編程語言包括C、C++等。支持多線程,充分利用CPU資源,支持多用戶。優(yōu)化的SQL查詢算法,有效地提高查詢速度。既能夠作為一個單獨的應用程序應用在客戶端服務(wù)器網(wǎng)絡(luò)環(huán)境中,也能夠作為一個庫而嵌入到其它的軟件中。提供多語言支持,常見的編碼如中文的GB2312、BIG5,日文的Shift_JIS等都可以用作數(shù)據(jù)表名和數(shù)據(jù)列名。提供TCP/IP、ODBC和JDBC等多種數(shù)據(jù)庫連接途徑。提供用于管理、檢查、優(yōu)化數(shù)據(jù)庫操作的管理工具??梢蕴幚頁碛猩锨f條記錄的大型數(shù)據(jù)庫。21.2.1MySQL簡介MySQL是一個廣受Linux社區(qū)歡迎的數(shù)據(jù)庫,很多Linux發(fā)行版都將其作為自身的一部分。與其它的大型數(shù)據(jù)庫例如Oracle、IBMDB2、SQLServer等相比,MySQL自有它的不足之處,如規(guī)模小、功能有限等,但對于中小型企業(yè)應用來說綽綽有余。MySQL支持大量的數(shù)據(jù)類型,并支持變長的BLOB(BinaryLargeOBject)類型。其中整型、浮點型和字符串類型可由用戶自定義字節(jié)長度,對整數(shù)字段由自動增量選項、日期時間字段也能很好的表示。MySQL提供了兩個相對不常用的字段類型:ENUM和SET。ENUM是一個枚舉類型,非常類適于C語言的枚舉類型,它允許程序員看到類似于MON、TUE、WED的字段值,而MySQL只將這些值存儲為一個字節(jié)。SET也是一個枚舉類型,但一個單獨字段一次可存儲多個值,這種存儲多個枚舉值的能力能獲得很好的性能提高。MySQL對SQL92標準進行了擴展,這些擴展彌補了SQL92標準已知的缺陷。不過,某些擴展需要在程序設(shè)計時格外注意。例如,LINK子句搜索對大小寫不敏感。MySQL允許用戶自行擴展SQL函數(shù),這些自定義函數(shù)不斷被其吸納,成為標準的一部分。所有函數(shù)必須編譯成動態(tài)連接庫文件,然后用LOADFUNCTION命令裝載到數(shù)據(jù)庫中。在三層結(jié)構(gòu)的應用中,這種特性可以減輕C語言程序設(shè)計的工作量,并且使數(shù)據(jù)處理獲得更高的性能。21.2.1MySQL簡介安裝MySQL可在其官方網(wǎng)站下載源代碼進行編譯,地址為:“”。或者在終端中輸入下列命令:yuminstallmysql-clientmysql-server-5.5libmysqlclient15-dev這三個程序分別是MySQL的客戶端、服務(wù)器和接口函數(shù)庫。安裝完成后將在系統(tǒng)中建立表所示的目錄。目錄路徑說
明/usr/binMySQL客戶端程序和腳本/usr/sbinmysqld服務(wù)器相關(guān)程序/var/lib/mysql日志文件,數(shù)據(jù)庫文件存放目錄/usr/share/doc/packages使用手冊,開發(fā)文檔存放目錄/usr/include/mysql接口函數(shù)庫頭文件存放目錄/usr/lib/mysql接口函數(shù)庫動態(tài)連接庫文件存放目錄/usr/share/mysql錯誤消息和字符集文件存放目錄/usr/share/sql-bench基本程序存放目錄21.2.1MySQL簡介安裝過程中完成后,程序會提示設(shè)置root用戶密碼,按照提示設(shè)置密碼后就完成了MySQL數(shù)據(jù)庫的安裝。初始化過程中可能會提示一些警告,但只要沒有錯誤信息,那么初始化就成功了,并且MySQL服務(wù)器就自動啟動了。可通過下列命令啟動和停止MySQL服務(wù)器:(1)啟動MySQL服務(wù)器servicemysqlstart(2)停止MySQL服務(wù)器servicemysqlstop21.2.1MySQL簡介這時即可用MySQL的標準客戶端連接服務(wù)器進行相關(guān)操作,連接命令如下:mysql-uroot–p
//以root用戶身份登錄服務(wù)器連接后MySQL服務(wù)器會提示輸入密碼,當終端的操作提示符變成“mysql>”,則代表已成功連接到本地計算機中的MySQL數(shù)據(jù)庫上。輸入“showdatabases;”命令可顯示服務(wù)器中所有的數(shù)據(jù)庫,代碼如下:mysql>showdatabases;+--------------------+|Database|+--------------------+|information_schema||test|+--------------------+2rowsinset(0.00sec)21.2.1MySQL簡介使用MySQL的標準客戶端可以進行所有的數(shù)據(jù)庫操作,但也有很多圖形化管理工具可供選擇。例如MySQLAdministrator,它是MySQL官方提供的圖形化管理器。在Ubuntu下可以訪問網(wǎng)址“”下載該程序的deb安裝包安裝該工具。Fedora下可以使用如下安裝命令安裝:yuminstallmysql-administratorMySQLAdministrator是用來執(zhí)行數(shù)據(jù)庫管理操作的程序,其中包括配置、控制、開啟和關(guān)閉MySQL服務(wù),并能管理用戶和連接數(shù),執(zhí)行數(shù)據(jù)備份和其它的一些管理任務(wù)。對于C語言開發(fā)者來說,使用該工具可簡化數(shù)據(jù)庫管理操作的難度,把更多精力放在程序設(shè)計工作上。21.2.2連接MySQL數(shù)據(jù)庫連接MySQL數(shù)據(jù)庫的C語言函數(shù)庫包含在mysql庫中,頭文件名稱為mysql.h。連接MySQL服務(wù)器時,應用程序應使用下列步驟進行操作。(1)通過調(diào)用mysql_library_init()函數(shù)初始化MySQL庫。庫可以是mysqlclientC客戶端庫,或mysqld嵌入式服務(wù)器庫,具體情況取決于應用程序編譯時是否與-libmysqlclient或-libmysqld標志鏈接。(2)通過調(diào)用mysql_init()函數(shù)初始化連接處理程序,并通過調(diào)用mysql_real_connect()函數(shù)連接到服務(wù)器。(3)通過調(diào)用mysql_close()函數(shù)關(guān)閉與MySQL服務(wù)器的連接。(4)通過調(diào)用mysql_library_end()函數(shù)結(jié)束MySQL庫的使用。21.2.2連接MySQL數(shù)據(jù)庫調(diào)用mysql_library_init()函數(shù)和mysql_library_end()函數(shù)的目的在于為MySQL庫提供恰當?shù)某跏蓟徒Y(jié)束處理。對于與客戶端庫鏈接的應用程序,它們提供了改進的內(nèi)存管理功能。如果不調(diào)用mysql_library_end()函數(shù),內(nèi)存塊仍將保持分配狀態(tài)而造成內(nèi)存泄漏。對于與嵌入式服務(wù)器鏈接的應用程序,這些調(diào)用會啟動并停止服務(wù)器。它們的一般形式為:intmysql_library_init(intargc,char**argv,char**groups);voidmysql_library_end(void);21.2.2連接MySQL數(shù)據(jù)庫調(diào)用任何其它MySQL函數(shù)之前,必須在使用嵌入式服務(wù)器的程序中調(diào)用mysql_library_init()函數(shù)。它將啟動服務(wù)器,并初始化服務(wù)器使用的任何子系統(tǒng)(mysys、InnoDB等)。函數(shù)中的argc和argv參數(shù)與主函數(shù)main()的相似,通常用于接收程序的執(zhí)行參數(shù)。argv的第1個元素將被忽略,它包含的是程序文件名。如果沒有程序的執(zhí)行參數(shù),argc可以是0。如果打算連接到外部服務(wù)器而不啟動嵌入式服務(wù)器,應為argc指定負值。groups中以Null終結(jié)的字符串列表選擇了選項文件中的活動groups。groups可以是NULL,在該情況下,[server]和[embedded]組是活動的。在所有其它MySQL函數(shù)后,程序中必須調(diào)用mysql_server_end()函數(shù)一次。它將關(guān)閉嵌入式服務(wù)器。(21_2_2.c)21.2.2連接MySQL數(shù)據(jù)庫要連接到服務(wù)器可調(diào)用mysql_init()函數(shù)來初始化連接處理程序,然后用該處理程序(以及其它信息,如主機名、用戶名和密碼)調(diào)用mysql_real_connect()函數(shù)。建立連接后,mysql_real_connect()函數(shù)會將再連接標志設(shè)置為0,該標志是數(shù)據(jù)庫標識符的一部分??梢栽趍ysql_options()函數(shù)上使用MYSQL_OPT_RECONNECT選項,以控制再連接行為。完成連接后,調(diào)用mysql_close()函數(shù)終止它。它們的一般形式是:MYSQL*mysql_init(MYSQL*mysql);MYSQL*mysql_real_connect(MYSQL*mysql,
//數(shù)據(jù)庫標識符
constchar*host,
//主機名
constchar*user,
//用戶名
constchar*passwd,
//用戶密碼
constchar*db,
//數(shù)據(jù)庫名
unsignedintport,
//端口號
constchar*unix_socket,
//套接字
unsignedlongclient_flag);
//客戶端標志voidmysql_close(MYSQL*mysql);21.2.2連接MySQL數(shù)據(jù)庫這3個函數(shù)使用MySQL結(jié)構(gòu)作為其標識符,使用前必須在程序中聲明。mysql_init()函數(shù)用于分配或初始化與mysql_real_connect()函數(shù)相適應的MySQL對象。如果mysql的實際參數(shù)是NULL指針,該函數(shù)將分配、初始化、并返回新對象。否則,將初始化對象,并返回對象的地址。如果mysql_init()函數(shù)分配了新的對象,應當調(diào)用mysql_close()函數(shù)來關(guān)閉連接,釋放該對象的內(nèi)存空間。如果無足夠內(nèi)存以分配新的對象,返回NULL。mysql_real_connect()函數(shù)嘗試與運行在主機上的MySQL數(shù)據(jù)庫引擎建立連接。在執(zhí)行需要有效MySQL連接句柄結(jié)構(gòu)的任何其它接口函數(shù)之前,mysql_real_connect()函數(shù)必須成功完成。函數(shù)第一個參數(shù)應是可用的MySQL結(jié)構(gòu)的地址。host參數(shù)的值必須是主機名或IP地址。如果host的實際參數(shù)是NULL或字符串localhost,連接將被視為與本地主機的連接。如果操作系統(tǒng)支持套接字,將使用它們而不是TCP/IP連接到服務(wù)器。user參數(shù)包含用戶的MySQL登錄ID。如果user是NULL或空字符串,用戶將被視為當前用戶。passwd參數(shù)包含用戶的密碼。如果passwd是NULL,僅會對該用戶的(擁有1個空密碼字段的)用戶表中的條目進行匹配檢查。21.2.2連接MySQL數(shù)據(jù)庫db參數(shù)是數(shù)據(jù)庫名稱。如果db的實際參數(shù)為NULL,連接會將默認的數(shù)據(jù)庫設(shè)為該值。如果port參數(shù)不是0,其值將用作TCP/IP連接的端口號,host參數(shù)決定了連接的類型。如果unix_socket參數(shù)不是NULL,該字符串描述了應使用的套接字。client_flag參數(shù)的值通常為0,但是,也能將其設(shè)置為如表所述標志的組合,以允許特定功能。參
數(shù)說
明PRESS使用壓縮協(xié)議CLIENT_FOUND_ROWS返回發(fā)現(xiàn)的行數(shù)(匹配的),而不是受影響的行數(shù)CLIENT_IGNORE_SPACE允許在函數(shù)名后使用空格。使所有的函數(shù)名成為保留字CLIENT_INTERACTIVE關(guān)閉連接之前,允許interactive_timeout(取代了wait_timeout)秒的不活動時間??蛻舳说臅抴ait_timeout變量被設(shè)為會話interactive_timeout變量的值CLIENT_LOCAL_FILES允許LOADDATALOCAL處理功能CLIENT_MULTI_STATEMENTS通知服務(wù)器,客戶端可能在單個字符串內(nèi)發(fā)送多條語句(由‘;’隔開)。如果未設(shè)置該標志,將禁止多語句執(zhí)行CLIENT_MULTI_RESULTS通知服務(wù)器,客戶端能夠處理來自多語句執(zhí)行或存儲程序的多個結(jié)果集。如果設(shè)置了CLIENT_MULTI_STATEMENTS,將自動設(shè)置它CLIENT_NO_SCHEMA禁止db_name.tbl_name.col_name語法。它用于ODBC。如果使用了該語法,它會使分析程序生成錯誤,在捕獲某些ODBC程序中的缺陷時,它很有用CLIENT_ODBC客戶端是ODBC客戶端。它將mysqld變得更為ODBC友好(Windows系統(tǒng)所使用的通用數(shù)據(jù)庫接口)CLIENT_SSL使用SSL(加密協(xié)議)。該選項不應由應用程序設(shè)置,它是在客戶端庫內(nèi)部設(shè)置的21.2.2連接MySQL數(shù)據(jù)庫對于某些參數(shù),能夠從選項文件獲得取值,而不是取得mysql_real_connect()函數(shù)調(diào)用中的確切值。因此,在調(diào)用mysql_real_connect()函數(shù)之前,應與MYSQL_READ_DEFAULT_FILE或MYSQL_READ_DEFAULT_GROUP選項一起調(diào)用mysql_options()函數(shù)。如果連接成功,返回MYSQL*連接標識符。如果連接失敗,返回NULL,并產(chǎn)生一個MySQL錯誤代碼,可以使用mysql_error()函數(shù)捕捉。連接錯誤代碼如表所示。代
碼說
明CR_CONN_HOST_ERROR無法連接到MySQL服務(wù)器CR_CONNECTION_ERROR無法連接到本地MySQL服務(wù)器CR_IPSOCK_ERROR無法創(chuàng)建IP套接字CR_OUT_OF_MEMORY內(nèi)存溢出CR_SOCKET_CREATE_ERROR無法創(chuàng)建UNIX套接字CR_UNKNOWN_HOST無法找到主機名的IP地址CR_VERSION_ERROR協(xié)議不匹配,起因于試圖連接到具有特定客戶端庫(該客戶端庫使用了不同的協(xié)議版本)的服務(wù)器。如果使用很早的客戶端庫來建立與較新的服務(wù)器(未使用“--old-protocol”選項開始的)的連接,就會出現(xiàn)該情況CR_NAMEDPIPEOPEN_ERROR無法在Windows平臺下創(chuàng)建命名管道CR_NAMEDPIPEWAIT_ERROR在Windows平臺下等待命名管道失敗CR_NAMEDPIPESETSTATE_ERROR在Windows平臺下獲取管道處理程序失敗CR_SERVER_LOST如果connect_timeout>0,而且在連接服務(wù)器時所用時間長于connect_timeout秒,或在執(zhí)行mand時服務(wù)器消失21.2.2連接MySQL數(shù)據(jù)庫mysql_close()函數(shù)關(guān)閉前面打開的連接。如果句柄是由mysql_init()函數(shù)或mysql_connect()函數(shù)自動分配的,mysql_close()還將解除分配由mysql指向的連接句柄。下面是連接MySQL數(shù)據(jù)庫的示例:
MYSQLmysql;
//聲明數(shù)據(jù)庫標識符
mysql_init(&mysql);
//初始化連接處理程序
mysql_options(&mysql,MYSQL_READ_DEFAULT_GROUP,"your_prog_name"); //建立數(shù)據(jù)庫
if(!mysql_real_connect(&mysql,"host","root","password","test",0,
NULL,0)){
//建立數(shù)據(jù)庫連接
fprintf(stderr,"無法連接數(shù)據(jù)庫,錯誤原因:%s\n",
mysql_error(&mysql));
//捕捉MySQL錯誤
}
else{
puts("數(shù)據(jù)庫連接成功");
mysql_close(&mysql);
//關(guān)閉數(shù)據(jù)庫連接
}21.2.3查詢MySQL數(shù)據(jù)庫當連接處于活動狀態(tài)時,客戶端程序可使用mysql_query()函數(shù)或mysql_real_query()函數(shù)向服務(wù)器發(fā)出SQL查詢。兩者的差別在于,mysql_query()函數(shù)預期的查詢?yōu)橹付ǖ?、由Null終結(jié)的字符串,而mysql_real_query()函數(shù)預期的是計數(shù)字符串。如果字符串包含二進制數(shù)據(jù)(其中可能包含Null字節(jié)),就必須使用mysql_real_query()函數(shù)。它們的一般形式是:intmysql_query(MYSQL*mysql,constchar*query);intmysql_real_query(MYSQL*mysql,constchar*query,unsignedlonglength);mysql_query()函數(shù)執(zhí)行由“Null終結(jié)的字符串”查詢指向的SQL查詢。正常情況下,字符串必須包含1條SQL語句,而且不應為語句添加終結(jié)分號(‘;’)或“\g”。如果允許多語句執(zhí)行,字符串可包含多條由分號隔開的語句。如果查詢成功,返回0。如果出現(xiàn)錯誤,返回非0值。可捕捉的錯誤代碼如表所示。代
碼說
明MANDS_OUT_OF_SYNC以不恰當?shù)捻樞驁?zhí)行了命令CR_SERVER_GONE_ERRORMySQL服務(wù)器不可用CR_SERVER_LOST在查詢過程中,與服務(wù)器的連接丟失CR_UNKNOWN_ERROR出現(xiàn)未知錯誤21.2.3查詢MySQL數(shù)據(jù)庫mysql_real_query()函數(shù)執(zhí)行由query指向的SQL查詢,它應是字符串長度字節(jié)long。正常情況下,字符串必須包含1條SQL語句,而且不應為語句添加終結(jié)分號(‘;’)或“\g”。如果允許多語句執(zhí)行,字符串可包含由分號隔開的多條語句。對于包含二進制數(shù)據(jù)的查詢,必須使用mysql_real_query()函數(shù)而不是mysql_query()函數(shù),這是因為,二進制數(shù)據(jù)可能會包含‘\0’字符。此外,mysql_real_query()函數(shù)比mysql_query()函數(shù)快,這是因為它不會在查詢字符串上調(diào)用strlen()函數(shù)。對于每個非SELECT查詢,例如INSERT、UPDATE、DELETE,通過調(diào)用mysql_affected_rows(),可發(fā)現(xiàn)有多少行已被改變(影響)。它的一般形式是:my_ulonglongmysql_affected_rows(MYSQL*mysql);函數(shù)的返回值為my_ulonglong類型的數(shù)值,該數(shù)值是影響的記錄數(shù)。如下例所示:
mysql_query(&mysql,"UPDATEcall_listSETcharge_rate=0.4WHEREtype=1");
//執(zhí)行一條SQL語句
printf("%ld條記錄被修改",(long)mysql_affected_rows(&mysql));
//返回查詢結(jié)果數(shù)目21.2.4處理MySQL查詢結(jié)果對于SELECT查詢,能夠檢索作為結(jié)果集的行。注意,某些語句因其返回行,類似于SELECT,包括SHOW、DESCRIBE和EXPLAIN,應按照對待SELECT語句的方式處理它們??蛻舳颂幚斫Y(jié)果集的方式有兩種。一種方式是,通過調(diào)用mysql_store_result()函數(shù)一次性地檢索整個結(jié)果集。該函數(shù)能從服務(wù)器獲得查詢返回的所有行,并將它們保存在客戶端。第二種方式是針對客戶端的,通過調(diào)用mysql_use_result()函數(shù),對“按行”結(jié)果集檢索進行初始化處理。該函數(shù)能初始化檢索結(jié)果,但不能從服務(wù)器獲得任何實際行。它們的一般形式是:MYSQL_RES*mysql_store_result(MYSQL*mysql);MYSQL_RES*mysql_use_result(MYSQL*mysql);21.2.4處理MySQL查詢結(jié)果1.使用mysql_store_result()函數(shù)進行查詢mysql_store_result()函數(shù)將查詢的全部結(jié)果讀取到客戶端,分配1個MYSQL_RES結(jié)構(gòu),并將結(jié)果置于該結(jié)構(gòu)中。如果查詢未返回結(jié)果集,mysql_store_result()函數(shù)將返回NULL指針(例如,如果查詢是INSERT語句)。如果讀取結(jié)果集失敗,mysql_store_result()函數(shù)還會返回NULL指針。通過檢查mysql_error()函數(shù)是否返回非空字符串,mysql_errno()函數(shù)是否返回非0值,或mysql_field_count()函數(shù)是否返回0,可以檢查是否出現(xiàn)了錯誤。2.使用mysql_use_result()函數(shù)進行查詢mysql_use_result()函數(shù)將初始化結(jié)果集檢索,但并不像mysql_store_result()函數(shù)那樣將結(jié)果集實際讀取到客戶端。它必須通過調(diào)用mysql_fetch_row()函數(shù)對每一行分別進行檢索。這將直接從服務(wù)器讀取結(jié)果,而不會將其保存在臨時表或本地緩沖區(qū)內(nèi),與mysql_store_result()函數(shù)相比,速度更快而且使用的內(nèi)存也更少??蛻舳藘H為當前行和通信緩沖區(qū)分配內(nèi)存,分配的內(nèi)存可增加到max_allowed_packet字節(jié)。另一方面,如果客戶端正在進行大量的數(shù)據(jù)庫處理操作,或者使用的是支持Ctrl+S操作(停止?jié)L動)的客戶端,就不應使用mysql_use_result()函數(shù)。這會綁定服務(wù)器,并阻止其它線程更新任何表(數(shù)據(jù)從這類表獲得)。21.2.4處理MySQL查詢結(jié)果3.訪問結(jié)果集在這兩種情況下,均能通過調(diào)用mysql_fetch_row()函數(shù)訪問行。對于mysql_store_result()函數(shù),mysql_fetch_row()函數(shù)能夠訪問以前從服務(wù)器獲得的行。對于mysql_use_result()函數(shù),mysql_fetch_row()函數(shù)能夠?qū)嶋H地檢索來自服務(wù)器的行。通過調(diào)用mysql_fetch_lengths()函數(shù),能獲得關(guān)于各行中數(shù)據(jù)大小的信息。完成結(jié)果集操作后,還需要調(diào)用mysql_free_result()函數(shù)釋放結(jié)果集使用的內(nèi)存。它們的一般形式是:MYSQL_ROWmysql_fetch_row(MYSQL_RES*result);unsignedlong
*mysql_fetch_lengths(MYSQL_RES*result);voidmysql_free_result(MYSQL_RES*result);mysql_fetch_row()函數(shù)檢索結(jié)果集的下一行。在mysql_store_result()函數(shù)之后使用時,如果沒有要檢索的行,mysql_fetch_row()函數(shù)返回NULL。在mysql_use_result()函數(shù)之后使用時,如果沒有要檢索的行或出現(xiàn)了錯誤,mysql_fetch_row()函數(shù)返回NULL。函數(shù)執(zhí)行成功時,返回值為下一行的MYSQL_ROW結(jié)構(gòu)。21.2.4處理MySQL查詢結(jié)果mysql_fetch_lengths()函數(shù)返回結(jié)果集內(nèi)當前行的列的長度,對于空列以及包含NULL值的列,其長度為0。如果打算復制字段值,該長度信息有助于優(yōu)化,這是因為能避免調(diào)用strlen()函數(shù)。此外,如果結(jié)果集包含二進制數(shù)據(jù),必須使用該函數(shù)來確定數(shù)據(jù)的大小。其原因在于,對于包含NULL字符的任何字段,strlen()函數(shù)將返回錯誤的結(jié)果。mysql_free_result()函數(shù)釋放由mysql_store_result()函數(shù)、mysql_use_result()函數(shù)為結(jié)果集分配的內(nèi)存。完成對結(jié)果集的操作后,必須調(diào)用mysql_free_result()函數(shù)釋放結(jié)果集使用的內(nèi)存。21.2.4處理MySQL查詢結(jié)果mysql_store_result()函數(shù)和mysql_use_result()函數(shù)的兩種檢索機制是互補的??蛻舳藨贸绦蚩蛇x擇與需求最為貼近的檢索機制。在實際應用中,mysql_store_result()函數(shù)較為常用。mysql_store_result()的優(yōu)點在于,所有的查詢行結(jié)構(gòu)都傳遞給了客戶端應用程序,不僅能連續(xù)訪問查詢結(jié)果,還能使用mysql_data_seek()函數(shù)或mysql_row_seek()函數(shù)在結(jié)果集中向前或向后移動,以更改結(jié)果集內(nèi)游標的位置。通過調(diào)用mysql_num_rows()函數(shù),還能發(fā)現(xiàn)有多少行。另一方面,對于大的結(jié)果集,mysql_store_result()函數(shù)所需的內(nèi)存可能會很大,很可能遇到內(nèi)存溢出狀況。mysql_use_result()函數(shù)的優(yōu)點在于,客戶端用于保存查詢結(jié)果集的內(nèi)存較少。這是因為每次執(zhí)行查詢操作,返回到客戶端的記錄只有一條,由于傳遞的查詢結(jié)構(gòu)較少,mysql_use_result()函數(shù)執(zhí)行速度更快。其缺點在于必須快速處理查詢結(jié)構(gòu),否則會影響服務(wù)器性能,因為查詢操作的會話依然存在。另外,不能隨機訪問結(jié)果集,只允許順序讀取每行記錄,并且無法知道查詢結(jié)構(gòu)的總行數(shù)。不僅如此,即使在檢索過程中已獲得所需要的結(jié)構(gòu),也必須檢索完所有的行。21.2.4處理MySQL查詢結(jié)果4.示例假設(shè)本機的MySQL服務(wù)器test數(shù)據(jù)庫內(nèi)已建立call_list表并保存有一些數(shù)據(jù),那么可以用下例將其中所有數(shù)據(jù)輸出。(21_2_4.c)程序中,首先為MySQL數(shù)據(jù)庫操作定義了執(zhí)行參數(shù),這些參數(shù)將用于創(chuàng)建與MySQL數(shù)據(jù)庫的連接。然后用mysql_library_init()函數(shù)初始化MySQL庫,用mysql_init()函數(shù)初始化連接處理程序。接著,使用mysql_real_connect()函數(shù)建立數(shù)據(jù)庫連接。如果數(shù)據(jù)庫連接建立成功,首先執(zhí)行查詢語句,查詢call_list表中的所有數(shù)據(jù),查詢結(jié)果保存在結(jié)果集中,然后以行為單位輸出所有查詢結(jié)果。待結(jié)果輸出完畢,使用mysql_free_result()函數(shù)清除結(jié)果集。最后使用mysql_close()函數(shù)關(guān)閉數(shù)據(jù)庫連接,并使用mysql_library_end()函數(shù)結(jié)束MySQL處理。21.3大型數(shù)據(jù)庫與通用數(shù)據(jù)庫接口前面章節(jié)介紹了一些小型和中型數(shù)據(jù)庫,但對于需要進行超大數(shù)據(jù)量存儲和管理的應用領(lǐng)域,如金融企業(yè)、航空運輸企業(yè),這些數(shù)據(jù)庫滿足不了需求。常用的大型數(shù)據(jù)庫有Oracle、Sybase、Informix和DB2等,雖然這些數(shù)據(jù)庫不是開源軟件,大部分不能運行在Linux系統(tǒng)上,但實際中仍然有在Linux系統(tǒng)中使用C語言開發(fā)客戶端訪問這些數(shù)據(jù)庫的需求。另外,如果能通過一個函數(shù)庫來訪問多種不同類型的數(shù)據(jù)庫,對于程序開發(fā)來說將減少很多重復勞動。本節(jié)將粗略地探討這些問題。21.3.1連接Oracle數(shù)據(jù)庫Oracle是最為著名的大型數(shù)據(jù)庫軟件之一,很多跨國集團和金融企業(yè)采用其大型數(shù)據(jù)庫構(gòu)件應用系統(tǒng)。Oracle以數(shù)據(jù)庫的優(yōu)勢建立起龐大的應用系統(tǒng),包括ERP、CRM等。Oracle數(shù)據(jù)庫運行平臺為企業(yè)級服務(wù)器、服務(wù)器集群和小型計算機,并支持磁盤陣列等數(shù)據(jù)倉庫級存儲系統(tǒng)。Oracle也是最早將SQL語言引入關(guān)系數(shù)據(jù)庫的開發(fā)者,同時擴展了共享SQL和多線索服務(wù)器體系結(jié)構(gòu)。該技術(shù)不僅降低Oracle系統(tǒng)開銷,而且增強了數(shù)據(jù)處理能力,使之能運行在Linux系統(tǒng)的普通服務(wù)器上。Oracle也是少數(shù)支持Linux系統(tǒng)的大型數(shù)據(jù)庫軟件之一,RedHatAS系列已能順利運行Oracle數(shù)據(jù)庫。數(shù)據(jù)的存儲形式上,Oracle以文件作為存儲單元,每個文件保存一個數(shù)據(jù)表。數(shù)據(jù)文件非常靈活,可隨著數(shù)據(jù)容量的增長而變化。邏輯結(jié)構(gòu)上,Oracle數(shù)據(jù)庫由表空間組成,這些表可分為系統(tǒng)表和用戶表。用戶表中可存儲數(shù)據(jù)、索引等信息。Oracle數(shù)據(jù)庫對網(wǎng)絡(luò)的支持非常好,甚至支持云計算。將多個運行Oracle數(shù)據(jù)庫的服務(wù)器組成服務(wù)器集群,可通過網(wǎng)絡(luò)組成一個數(shù)據(jù)中心,并實現(xiàn)系統(tǒng)負載均衡和異地數(shù)據(jù)自動備份等功能。服務(wù)器協(xié)同工作對開發(fā)者是透明的,開發(fā)者不用額外付出勞動。21.3.1連接Oracle數(shù)據(jù)庫在數(shù)據(jù)復制方面,Oracle提供了實時復制、定時復制和儲存轉(zhuǎn)發(fā)復制等多種功能,可快速為數(shù)據(jù)庫建立副本,并在復制過程中利用自動沖突檢測提供有效的沖突解決機制。例如,使用網(wǎng)絡(luò)連接的兩個Oracle數(shù)據(jù)庫之間可通過數(shù)據(jù)庫連接建立訪問機制,數(shù)據(jù)可均勻地分散在兩地。PL/SQL是Oracle對SQL92標準的擴展,除了數(shù)據(jù)訪問、數(shù)據(jù)管理和數(shù)據(jù)庫管理功能以外,PL/SQL可靈活地開發(fā)各種存儲過程。這些存儲過程執(zhí)行效率高于C語言的函數(shù)調(diào)用機制,為數(shù)據(jù)層和業(yè)務(wù)層分離打下了良好的基礎(chǔ)。Linux系統(tǒng)上Oracle的C語言接口函數(shù)庫名稱為OCI(OracleCommonInterface)C-Library,該函數(shù)庫是一個功能強大的數(shù)據(jù)庫操作模塊。它支持事務(wù)處理,單事務(wù)中的多連接多數(shù)據(jù)源操作,支持數(shù)據(jù)的對象訪問、存儲過程的調(diào)用等一系列高級應用,并對Oracle下的多種附加產(chǎn)品提供接口。但是為了使OCI庫在多種平臺上保持統(tǒng)一的風格并考慮向下兼容性,其內(nèi)部將大量的C語言類型和代碼進行了重新封裝,這使得OCI庫看上去顯得紛繁復雜,開發(fā)者難以掌握。21.3.1連接Oracle數(shù)據(jù)庫Libsqlora8庫是另一種選擇,它使得在Linux下Oracle的非高端C語言開發(fā)變得比較方便易用。Libsqlora8for*nix是GNU/Linux組織開發(fā)的針對Oracle8OCIlibrary的易用性C語言封裝。其特點為,將大量的OCI數(shù)據(jù)類型轉(zhuǎn)換為通用C語言數(shù)據(jù)類型,并且將OCI函數(shù)按分類重新封裝,從而減少了函數(shù)的調(diào)用步驟和程序代碼量。Libsqlora8還有許多引人注目的特性。易于使用的動態(tài)SQL語句。同一連接中具有不同變量綁定的游標的重復打開功能。相同事務(wù)中支持多數(shù)據(jù)庫連接。Oracle數(shù)據(jù)庫應用開發(fā)具備內(nèi)建軌跡功能。能正確處理數(shù)據(jù)插入操作中的數(shù)組變量??梢宰鳛殪o態(tài)或動態(tài)形式鏈接進入應用程序。21.3.1連接Oracle數(shù)據(jù)庫安裝Libsqlora8需在其項目主頁上下載源文件編譯,地址為。安裝命令如下:gunzip-clibsqlora8-2.3.3.tar.gz|tarxf- //解壓源碼包cdlibsqlora8-2.3.3 //進入解壓后源代碼文件目錄LD_LIBRARY_PATH=$ORACLE_HOME/lib//配置環(huán)境變量exportLD_LIBRARY_PATH //立即更新環(huán)境變量./configure //配置源代碼執(zhí)行環(huán)境make //編譯源代碼makeinstall //安裝程序Libsqlora8庫的函數(shù)包含在頭文件sqlora.h中,常用的函數(shù)及功能如后圖表所示。函
數(shù)
名說
明intsqlo_init(intthreaded_mode);初始化程序庫接口,讀出環(huán)境變量,設(shè)置相應的全局變量。當前,threaded_mode設(shè)為0intsqlo_connect(int*dbh,char*connect_str);連接數(shù)據(jù)庫,dbh為數(shù)據(jù)庫連接描述符,connect_str為用戶名/口令字符串intsqlo_finish(intdbh);斷開數(shù)據(jù)庫連接intsqlo_open(intdbh,char*stmt,intargc,char*argv[]);打開由stmt確定的查詢語句所返回的游標。Argc、argv為查詢的參數(shù),后面將用更清晰的方法傳遞參數(shù)intsqlo_close(intsth);關(guān)閉由上一個函數(shù)打開的游標intsqlo_fetch(intsth);從打開的游標中獲取一條記錄,并將之存入一個已分配內(nèi)存空間中constchar**sqlo_values(intsth,int*numbalues,intdostrip);從內(nèi)存中返回上一次sqlo_fetch取得的值,是以字符串形式返回的intsqlo_prepare(intdbh,charconst*stmt);返回一個打開的游標sthintsqlo_bind_by_name(intsth,constchar*
param_name,intparam_type,constvoid*param_addr,unsignedintparam_size,short*ind_arr,intis_array);將查詢語句的傳入?yún)?shù),按照名字的形式與函數(shù)中的變量綁定。如果使用數(shù)組,那么參數(shù)param_addr和ind_arr必須指向該數(shù)組intsqlo_bind_by_pos(intsth,intparam_pos,intparam_type,constvoid*param_addr,unsignedintparam_size,short*ind_arr,intis_array);將查詢語句的傳出值,按照位置順序與函數(shù)中的變量綁定intsqlo_execute(intsth,intiterations);執(zhí)行查詢語句。Iterations可設(shè)為1intmit(intdbh);提交查詢操作intsqlo_rollback(intdbh);回滾操作,撤銷前面對數(shù)據(jù)庫所做的改變21.3.1連接Oracle數(shù)據(jù)庫與其它數(shù)據(jù)庫相同,在進行數(shù)據(jù)查詢操作前,首先必須進行數(shù)據(jù)庫連接。(21_3_1.c)本例的作用是連接到本地Oracle數(shù)據(jù)庫服務(wù)器中,系統(tǒng)中必須安裝有Oracle客戶端程序,通常需要一張Oracle數(shù)據(jù)庫的安裝光盤才能完成。Oracle數(shù)據(jù)庫服務(wù)器的位置在Oracle客戶端中設(shè)置,只有企業(yè)版的Linux上才有可能成功安裝Oracle數(shù)據(jù)庫服務(wù)器。21.3.2通用數(shù)據(jù)庫接口當以三層模型作為設(shè)計應用程序的準則時,開發(fā)者通常希望邏輯層對于數(shù)據(jù)層的訪問不受制于某一種數(shù)據(jù)庫的接口。如果在程序中將所有常用的數(shù)據(jù)庫的接口考慮在內(nèi),不僅會使程序開發(fā)的工作量大大增加,重復出現(xiàn)許多冗余的數(shù)據(jù)庫訪問代碼,還會因某一種數(shù)據(jù)庫的升級或變更使應用程序的通用性大打折扣。開發(fā)者迫切需要一種能夠?qū)Χ喾N數(shù)據(jù)庫進行連接和訪問、可自動在不同數(shù)據(jù)庫的數(shù)據(jù)類型間自動轉(zhuǎn)換、使用接近于SQL92標準的數(shù)據(jù)庫查詢語言的通用數(shù)據(jù)庫接口。在Linux系統(tǒng)中,有兩種方式能夠滿足開發(fā)者的需求。第一種是選擇通用數(shù)據(jù)庫接口函數(shù)庫,例如SQLRelay,它可以同時支持十余種常用的數(shù)據(jù)庫,并且能通過相同的C語言函數(shù)對這些數(shù)據(jù)庫進行連接和訪問。這種方式實際上是將多種數(shù)據(jù)庫的接口函數(shù)封裝在同一個函數(shù)庫內(nèi),因為數(shù)據(jù)庫接口函數(shù)之間本身有很大的差異,它并不能非常及時地應對某一種數(shù)據(jù)庫接口的變更。另一種方式是選擇通用數(shù)據(jù)庫連接池,這是一種中間件,即建立在數(shù)據(jù)庫與應用程序之間的程序。雖然使用數(shù)據(jù)庫連接池會消耗一些額外的系統(tǒng)資源,但它能更好地滿足訪問多種數(shù)據(jù)庫的需求,很多數(shù)據(jù)庫在開發(fā)時即考慮了對數(shù)據(jù)庫連接池的支持,所以不會因為數(shù)據(jù)庫的升級或變更造成太大影響。21.3.2通用數(shù)據(jù)庫接口Linux系統(tǒng)中最常用的數(shù)據(jù)庫連接池為unixODBC,它不僅支持眾多數(shù)據(jù)庫,還能通過插件的形式增加對新的數(shù)據(jù)庫的支持。unixODBC(UNIXOpenDatabaseConnect)即UNIX系統(tǒng)中開放數(shù)據(jù)庫互連的簡稱,它是一個用于訪問數(shù)據(jù)庫的統(tǒng)一界面標準,作為應用程序和數(shù)據(jù)庫系統(tǒng)之間的中間件。unixODBC主要由數(shù)據(jù)庫驅(qū)動程序和驅(qū)動程序管理器組成。驅(qū)動程序是一個用于支持unixODBC函數(shù)調(diào)用的模塊,每個驅(qū)動程序?qū)谝粋€數(shù)據(jù)庫系統(tǒng)。如果要改變應用程序所使用的數(shù)據(jù)庫,只需更改應用程序中由unixODBC管理程序設(shè)定的與相應數(shù)據(jù)庫系統(tǒng)對應的別名即可。驅(qū)動程序管理器可插入到所有unixODBC應用程序中,可用于管理應用程序中unixODBC函數(shù)與“.so”中函數(shù)的綁定。unixODBC使用層次的方法來管理數(shù)據(jù)庫,將數(shù)據(jù)庫通信結(jié)構(gòu)劃分為多個層次。如果操作依賴某種數(shù)據(jù)庫系統(tǒng)自身特性,unixODBC可以用公共接口解決潛在的不一致性。這種模式能很好地解決基于多個數(shù)據(jù)庫系統(tǒng)的應用程序的復雜性,也是unixODBC獲得巨大成功的重要原因之一。unixODBC的工作原理如后圖所示。21.3.2通用數(shù)據(jù)庫接口21.3.2通用數(shù)據(jù)庫接口從結(jié)構(gòu)上分,unixODBC分為單束式和多束式兩種,分別對應著單束式驅(qū)動程序和多束式驅(qū)動程序。單束式驅(qū)動程序如果公共接口一樣,為多種數(shù)據(jù)庫系統(tǒng)提供一個統(tǒng)一的數(shù)據(jù)訪問方式,介于應用程序和數(shù)據(jù)庫系統(tǒng)之間。單束式驅(qū)動程序介于應用程序和數(shù)據(jù)庫之間,像中介驅(qū)動程序一樣數(shù)據(jù)提供一個統(tǒng)一的數(shù)據(jù)訪問方式。在應用程序使用unixODBC操作數(shù)據(jù)庫時,unixODBC傳遞操作指令到unixODBC驅(qū)動程序管理器。然后,unixODBC驅(qū)動程序管理器對數(shù)據(jù)庫進行相應操作,并且將處理結(jié)果傳遞給unixODBC驅(qū)動程序管理器,最后傳遞到應用程序中。因此,單束式驅(qū)動程序是虛擬化的數(shù)據(jù)庫引擎,應用程序以unixODBC驅(qū)動程序管理器作為操作對象,而無需關(guān)系真實數(shù)據(jù)庫的情況。多束式驅(qū)動程序相對較為簡單,其工作方式只是在應用程序和數(shù)據(jù)庫系統(tǒng)間傳遞操作指令,而操作結(jié)果由數(shù)據(jù)庫系統(tǒng)直接傳遞給應用程序。當應用程序提交對數(shù)據(jù)庫操作的請求時,該請求被傳送到unixODBC驅(qū)動程序管理器。unixODBC驅(qū)動程序管理器首先對請求進行判斷,然后在應用程序和數(shù)據(jù)庫間建立相關(guān)連接。多束式驅(qū)動程序是數(shù)據(jù)庫通信接口的翻譯器,只是統(tǒng)一了多種數(shù)據(jù)庫系統(tǒng)的調(diào)用接口。例如,將Oracle的OCI函數(shù)庫翻譯為unixODBC函數(shù)庫。21.3.2通用數(shù)據(jù)庫接口安裝unixODBC可在其官方網(wǎng)站下載源代碼進行編譯,地址為“.org”,或在終端中輸入下列命令:apt-getinstallunixODBCunixODBC-dev如果Linux系統(tǒng)使用的是KDE界面,那么可以用ODBCConfig程序來進行unixODBC的配置,它的路徑為“/usr/bin”,如圖21.5所示。對于GNOME界面或其它界面的Linux系統(tǒng),可以使用shall上的isql工具進行unixODBC的配置。以連接Oracle數(shù)據(jù)庫為例,首先在“/etc/odbc.ini”文件中新建一個DSN,增加下列內(nèi)容:[ODBCDataSources]test=OracleODBCDriverDSN[default]Driver=/usr/local/easysoft/oracle/libesoracle.so[test]Driver=/usr/local/easysoft/oracle/libesoracle.soDescription=Oracleserver=1 //Oracle數(shù)據(jù)庫服務(wù)器的地址ServerType=OraclePort=1521 //端口號User=test1234 //用戶名Password
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 云南省新型城鎮(zhèn)化與糧食安全耦合協(xié)調(diào)發(fā)展及其驅(qū)動機制研究
- A公司基層員工的工作壓力及管理對策研究
- D房地產(chǎn)公司財務(wù)風險控制研究
- 肌肽通過靶向Caspase-1調(diào)控焦亡減輕順鉑誘導的急性腎損傷
- 經(jīng)營風險視角下的易安財險破產(chǎn)重整案例研究
- 坡面含沙水流對滾波特征參數(shù)的影響
- 2025年南陽職業(yè)學院高職單招語文2018-2024歷年參考題庫頻考點含答案解析
- 2025年六安職業(yè)技術(shù)學院高職單招語文2018-2024歷年參考題庫頻考點含答案解析
- 羽絨服的舒適度與保暖性能平衡研究-洞察分析
- 2025年云南交通職業(yè)技術(shù)學院高職單招數(shù)學歷年(2016-2024)頻考點試題含答案解析
- 定額〔2025〕1號文-關(guān)于發(fā)布2018版電力建設(shè)工程概預算定額2024年度價格水平調(diào)整的通知
- 2024年城市軌道交通設(shè)備維保及安全檢查合同3篇
- 【教案】+同一直線上二力的合成(教學設(shè)計)(人教版2024)八年級物理下冊
- 湖北省武漢市青山區(qū)2023-2024學年七年級上學期期末質(zhì)量檢測數(shù)學試卷(含解析)
- 單位往個人轉(zhuǎn)賬的合同(2篇)
- 科研倫理審查與違規(guī)處理考核試卷
- GB/T 44101-2024中國式摔跤課程學生運動能力測評規(guī)范
- 高危妊娠的評估和護理
- 2024年山東鐵投集團招聘筆試參考題庫含答案解析
- 2023年高考全國甲卷數(shù)學(理)試卷【含答案】
- 數(shù)獨題目A4打印版無答案
評論
0/150
提交評論