5.1 MySQL 可用的API
為了方便應(yīng)用程序的開發(fā),MySQL 提供了用C 編程語(yǔ)言編寫的客戶機(jī)庫(kù),它允許從任何C 程序的內(nèi)部訪問(wèn)MySQL 數(shù)據(jù)庫(kù)??蛻魴C(jī)庫(kù)實(shí)現(xiàn)應(yīng)用程序編程接口( A P I),API 定義客戶機(jī)程序如何建立和執(zhí)行與服務(wù)器的通信。
然而,使用C 來(lái)編寫MySQL 程序并不受限制。許多其他語(yǔ)言處理器本身也是由C 編寫的,或具有使用C庫(kù)的能力,所以MySQL 客戶機(jī)庫(kù)提供了這個(gè)方法,由此, MySQL 對(duì)這些語(yǔ)言的約束可以建立在C API 的上面。這就為與MySQL 服務(wù)器通信而編寫應(yīng)用程序提供了許多選擇??蛻魴C(jī)程序的API 是用Perl、PHP、Java、Python、C++、Tcl 和其他一些語(yǔ)言編寫的。有關(guān)最新的清單,請(qǐng)查看MySQL 參考指南或MySQL Web 站點(diǎn),因?yàn)橛袝r(shí)會(huì)增加用新語(yǔ)言編寫的A P I。
每種語(yǔ)言約束都定義自己的接口,特別是訪問(wèn)MySQL 的規(guī)則。這里沒有足夠的時(shí)間來(lái)討論MySQL 可使用的每種A P I,我們只講述最流行的三種:
■ C 客戶機(jī)庫(kù)A P I。這是MySQL 的基本編程接口。
■ Perl 通用目標(biāo)腳本語(yǔ)言的D B I(數(shù)據(jù)庫(kù)接口) A P I。DBI 是作為與其他模塊在D B D(數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序)級(jí)接口的Perl 模塊來(lái)實(shí)現(xiàn)的,每個(gè)模塊都提供對(duì)特定類型的數(shù)據(jù)庫(kù)引擎的訪問(wèn)(當(dāng)然,我們將討論的特定的DBD 模塊也提供對(duì)MySQL 的支持)。DBI 對(duì)MySQL 的最普遍用法是編寫由命令行來(lái)調(diào)用的獨(dú)立的客戶機(jī),以及試圖由Web 服務(wù)器調(diào)用的腳本來(lái)提供Web 對(duì)MySQL 的訪問(wèn)。
■ PHP API。PHP 是一種腳本語(yǔ)言,它提供了在Web 頁(yè)中嵌入程序的一種便利的方法。在發(fā)送以前,這樣的頁(yè)面由P H P來(lái)處理,它允許這些腳本生成動(dòng)態(tài)的內(nèi)容,如在頁(yè)面中包括MySQL 查詢的結(jié)果。“P H P”原始的意思是個(gè)人主頁(yè)( Personal Home Page),但是PHP 的成長(zhǎng)已經(jīng)遠(yuǎn)遠(yuǎn)超過(guò)它簡(jiǎn)單的原始功能。PHP Web 站點(diǎn)現(xiàn)在使用的這個(gè)名稱表示“P H P:超文本預(yù)處理程序( Hypertext Preprocessor)”,它像GNU (是GUN而不是UNIX )一樣以同樣的方式自我引用。
使用他人成果
當(dāng)標(biāo)準(zhǔn)的M y S Q L客戶機(jī)不能滿足需要時(shí),您并不總是需要編寫自己的程序。其他一些人一直編寫程序,而這些程序中有許多是可共享得到的。請(qǐng)參閱附錄I 中的一些樣例。只要找到幾個(gè)就能節(jié)省您的許多工作。
以上這三種A P I都有專門章節(jié)詳細(xì)說(shuō)明。本章只提供對(duì)API 比較的概述,用來(lái)說(shuō)明它們的基本特征,并給出對(duì)特定的應(yīng)用程序可能選擇某個(gè)而不是其他API 的原因。
當(dāng)然,不必只考慮某個(gè)API,應(yīng)了解每個(gè)API,并用可以明智選擇適合自己的API。在包括若干組件的大項(xiàng)目中,可能使用多個(gè)API,多種語(yǔ)言,這取決于每個(gè)子任務(wù)適合哪一種語(yǔ)言。
對(duì)于試圖使用的任何一種API,如果需要得到必需的軟件,請(qǐng)參閱附錄A。
5.1.1 C API
CAPI 用于編譯C 程序上下文環(huán)境內(nèi)部。它是一種客戶機(jī)庫(kù),提供可用來(lái)與MySQL服務(wù)器對(duì)話的最低級(jí)別的接口——具有創(chuàng)建與服務(wù)器通信所需的能力。DBI 和PHP 的前身DBI 的Perl 前身是Mysqlperl 模塊M y s q l . p m。這個(gè)模塊不再被支持,而且不應(yīng)該用于新的MySQL 的開發(fā)。有一件事需要明白,Mysqlperl 是依賴于MySQL 的,但DBI 不是。如果編寫MySQL 的Perl 應(yīng)用程序,然后,決定想用另外一種數(shù)據(jù)庫(kù)引擎來(lái)使用它們,則移植DBI 腳本比Mysqlperl 腳本更容易一些,因?yàn)樗鼈兒苌僖蕾囉谔囟ǖ臄?shù)據(jù)庫(kù)引擎。
如果獲取了訪問(wèn)MySQL 的一段Perl 腳本,并發(fā)現(xiàn)它是用Mysqlperl 而不是DBI 編寫的,則仍然可以使用D B I。DBI 包括了對(duì)Mysqlperl 的仿真支持,因此不需要安裝兩個(gè)程序包。PHP 3 的前身是PHP/FI 2.0 (F I代表“ form interpreter ,即格式解釋程序”)。像Mysqlperl 一樣,P H P / F I也是過(guò)時(shí)的,所以我們就不再進(jìn)一步討論它了。
MySQL C API 的起源如果已經(jīng)有編寫mSQL RDBMS 程序的經(jīng)驗(yàn),那么將注意到MySQL C API 類似于mSQL 相應(yīng)的C API。當(dāng)MySQL 的開發(fā)者們開始實(shí)現(xiàn)他們的SQL 引擎時(shí),許多有用的共享實(shí)用程序可用于m S Q L。要想花費(fèi)最小的難度將那些mSQL 實(shí)用程序移植為MySQL 的
實(shí)用程序是可能的,可有意地將MySQL API設(shè)計(jì)為與mSQL API 類似(MySQL 甚至帶有與mSQL API 函數(shù)名稱相應(yīng)的MySQL 名稱的簡(jiǎn)單的文本替代品的msql2mysql 腳本。這個(gè)操作相對(duì)煩瑣,實(shí)際上也照顧了許多涉及為使用MySQL 而轉(zhuǎn)換mSQL 程序的工作)。
MySQL 分發(fā)包提供的C 客戶機(jī)是基于這個(gè)API 的。C 客戶機(jī)庫(kù)也作為MySQL 對(duì)其他語(yǔ)言約束的基礎(chǔ)來(lái)提供服務(wù),但Java API 是一個(gè)例外。例如,通過(guò)連接MySQL C 客戶機(jī)庫(kù)代碼(這個(gè)過(guò)程在附錄A中通過(guò)DBI 和PHP 安裝指導(dǎo)來(lái)舉例說(shuō)明),M y S Q L可用Perl DBI 模塊專有的MySQL 驅(qū)動(dòng)程序和PHP 代碼。
5.1.2 Perl DBI API
DBI API 用于Perl 腳本語(yǔ)言編寫的應(yīng)用程序的上下文環(huán)境內(nèi)部。這種API 在我們考慮的這三種API 結(jié)構(gòu)中是最高的,因?yàn)樗膳c許多數(shù)據(jù)庫(kù)工作,而同時(shí)在腳本中可忽略許多特定數(shù)據(jù)庫(kù)的細(xì)節(jié)。DBI 經(jīng)過(guò)使用兩級(jí)結(jié)構(gòu)的Perl 模塊來(lái)實(shí)現(xiàn)(請(qǐng)參閱圖5 - 1):
■ DBI (數(shù)據(jù)庫(kù)接口)級(jí)。為客戶機(jī)腳本提供接口。這個(gè)級(jí)別提供的是抽象接口,并不是指特定數(shù)據(jù)庫(kù)引擎。
■ DBD (數(shù)據(jù)庫(kù)驅(qū)動(dòng)器)級(jí)。在這個(gè)級(jí)別由特定引擎的驅(qū)動(dòng)程序來(lái)提供對(duì)各種數(shù)據(jù)庫(kù)引擎的支持。

MySQL 對(duì)DBI 的支持環(huán)境由Msql - Mysql - modules分發(fā)包提供。這個(gè)模塊在DBD 級(jí)操作??梢詮姆职l(fā)包名稱及圖5 - 1中分辨它,一個(gè)驅(qū)動(dòng)程序可以提供對(duì)一個(gè)以上的RDBMS 的支持。Msql-Mysql-Modules 最初是為mSQL 而編寫的,后來(lái)擴(kuò)展到M y S Q L。這種影響類似于對(duì)mSQL 和MySQL 的CAPI。由于設(shè)計(jì)的MySQL CAPI 類似于mSQL CAPI,所以將mSQL DBD(使用mSQL C API)擴(kuò)展到對(duì)MySQL 的使用很有意義。
DBI 體系結(jié)構(gòu)編寫應(yīng)用程序的風(fēng)格相對(duì)普通。當(dāng)編寫DBI 腳本時(shí),可使用一組標(biāo)準(zhǔn)的調(diào)用。DBI 級(jí)在DBD 級(jí)調(diào)用適當(dāng)?shù)尿?qū)動(dòng)程序來(lái)處理請(qǐng)求,對(duì)于想使用的特定數(shù)據(jù)庫(kù)服務(wù)器通信中包括的特定問(wèn)題,由驅(qū)動(dòng)程序處理。DBD 級(jí)傳送從服務(wù)器返回的數(shù)據(jù),備份到DBI 級(jí),使
數(shù)據(jù)出現(xiàn)在應(yīng)用程序中。數(shù)據(jù)的格式與數(shù)據(jù)庫(kù)的數(shù)據(jù)來(lái)源一致。
其結(jié)果得到這樣一個(gè)接口,該接口從應(yīng)用程序的編寫者的觀點(diǎn)隱藏了數(shù)據(jù)庫(kù)引擎之間的差異,這樣可使用多種不同的引擎——和驅(qū)動(dòng)程序一樣多。DBI 通過(guò)允許以統(tǒng)一風(fēng)格訪問(wèn)每個(gè)數(shù)據(jù)庫(kù)來(lái)提供一致性客戶接口以增加可移植性。
當(dāng)打開數(shù)據(jù)庫(kù)時(shí),出現(xiàn)由腳本編寫的數(shù)據(jù)庫(kù)專有的界面。當(dāng)創(chuàng)建連接時(shí),應(yīng)指出使用哪個(gè)驅(qū)動(dòng)程序。例如,要想使用MySQL 數(shù)據(jù)庫(kù),應(yīng)這樣連接:

而要想使用Postgres 或m S Q L,應(yīng)這樣連接:

連接以后,對(duì)該驅(qū)動(dòng)程序不需要再做任何做特殊的引用。讓DBI 和該驅(qū)動(dòng)程序解決數(shù)據(jù)庫(kù)專有的細(xì)節(jié)。
無(wú)論如何這都是理論問(wèn)題。然而,至少有兩個(gè)因素與DBI 腳本的可移植性矛盾:
■ 在RDBMS 引擎之間SQL 的實(shí)現(xiàn)不同,為一個(gè)引擎編寫的SQL 另一個(gè)引擎根本不理解是完全可能的。如果SQL 相當(dāng)通用,則腳本可在引擎之間作相應(yīng)的移植。但如果SQL 依賴于引擎,則腳本也是這樣。例如,如果使用MySQL 指定的SHOW TABLES語(yǔ)句,則該腳本不能用其他數(shù)據(jù)庫(kù)執(zhí)行。
■ DBD 模塊通常提供引擎專有類型的信息來(lái)允許腳本編寫者使用特定數(shù)據(jù)庫(kù)系統(tǒng)的特定功能。例如, MySQL DBD 提供訪問(wèn)查詢結(jié)果中列屬性的方法,如每列的最大長(zhǎng)度、列是否是數(shù)值型的,等等。而這些屬性在其他數(shù)據(jù)庫(kù)中沒有任何相似物。DBD 專有的特性與可移植性相背,通過(guò)使用它們,將MySQL 編寫的腳本用于其他數(shù)據(jù)庫(kù)系統(tǒng)是困難的(然而,在第7章中,您將發(fā)現(xiàn),筆者毫不費(fèi)力地避免了由MySQL DBD 提供的MySQL 專有的結(jié)構(gòu)。那是因?yàn)槟鷳?yīng)該知道那些結(jié)構(gòu)是什么,以便可以決定自己是否使用它們)。
盡管存在數(shù)據(jù)庫(kù)專有腳本的這兩個(gè)因素,但以抽象方式提供數(shù)據(jù)庫(kù)訪問(wèn)的DBI 機(jī)制是完成可移植性的合理方式,只要您決定利用它多少次即可。
5.1.3 PHP API
像Perl 一樣,PHP 也是一種腳本語(yǔ)言。但它與Perl 不同,PHP 很少作為通用目標(biāo)語(yǔ)言來(lái)設(shè)計(jì),而是作為編寫Web 應(yīng)用程序的一種語(yǔ)言。PHP API 主要作為在Web 頁(yè)面中嵌入可執(zhí)行腳本的一種方法來(lái)使用。這使Web 的開發(fā)者們很容易用動(dòng)態(tài)生成上下文環(huán)境來(lái)編寫頁(yè)面。
當(dāng)客戶瀏覽器向Web 服務(wù)器發(fā)送PHP 頁(yè)面的請(qǐng)求時(shí),PHP 執(zhí)行在該頁(yè)面中它所發(fā)現(xiàn)的任何腳本,并用腳本的輸出來(lái)替換它。該結(jié)果再送回瀏覽器。這就使瀏覽器中實(shí)際出現(xiàn)的頁(yè)面根據(jù)請(qǐng)求的頁(yè)面環(huán)境的不同而有所不同。例如,當(dāng)在Web 頁(yè)面中嵌入下面簡(jiǎn)短的PHP 腳本時(shí),它出現(xiàn)所請(qǐng)求頁(yè)面的主機(jī)I P地址:

可以使用腳本為訪問(wèn)者提供基于數(shù)據(jù)庫(kù)上下文環(huán)境的最新信息。下面的樣例說(shuō)明可用于Historical League Web 站點(diǎn)的一個(gè)簡(jiǎn)單腳本。該腳本發(fā)布一個(gè)請(qǐng)求來(lái)確定當(dāng)前的League 的成員數(shù)目,并將該數(shù)目報(bào)告給訪問(wèn)該站點(diǎn)的人(如果出現(xiàn)錯(cuò)誤,則該腳本不報(bào)告任何數(shù)目):

DBI和DBD的含義
盡管DBI 級(jí)是獨(dú)立于數(shù)據(jù)庫(kù)的,而DBD 級(jí)是依賴于數(shù)據(jù)庫(kù)的,但那并不是“ DBI”和“DBD”所代表的意義。它們的意思是“數(shù)據(jù)庫(kù)接口”和“數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序”。
PHP 腳本通??雌饋?lái)像是帶有嵌入在“ <?p h p”和“?>”標(biāo)識(shí)符中的腳本的HTML 頁(yè)面。一個(gè)頁(yè)面可能包括若干個(gè)腳本。這為腳本的開發(fā)提供了一種非常靈活的方法。例如,如果您喜歡,可以編寫一個(gè)正常的HTML 頁(yè)面來(lái)創(chuàng)建通用的頁(yè)面框架,然后再增加腳本的內(nèi)
容。
對(duì)于不同的數(shù)據(jù)庫(kù)引擎,PHP 對(duì)統(tǒng)一的接口不再作任何事情, DBI 也用這種方法。取而代之,每個(gè)引擎的接口看起來(lái)非常像相應(yīng)的實(shí)現(xiàn)該引擎低級(jí)API 的C 庫(kù)接口。例如,用于從PHP 腳本內(nèi)部訪問(wèn)MySQL 的PHP 函數(shù)的名稱非常類似于MySQL C 客戶庫(kù)中函數(shù)的名稱。